# @Time : 2021/5/15 15:41
# @Author : Fioman
# @Phone : 13149920693
"""
图像处理程序,主要用来做图像视觉处理算法来使用
"""
import time

from tools.config_params import ConfigParams
from vision_process.image_operation import *
from tools.hd_logger import HdLogger
from db_tools.db_handler import DbHandler
from vision_process.image_process_common import check_total_board_is_ok, find_first_edge_line, find_third_edge_line, get_board_without_angle_3

cp = ConfigParams()
logger = HdLogger()
db = DbHandler()
upDownSlice = int(50 * cp.mm2pix)
jointLinePos = 1223
jointLineExtend = 23
jointLineFillSize = 25
innerToEdgeThres = 5
minLineLength = int(20 * cp.mm2pix)  # 线条最短是多少,50个mm
lineLengthMin = 20 * cp.mm2pix
maxLineGap = 5
tryBeginIndex = 1
leftRightLineOffsetThres = 100  # 单位mm
calcArgsNormal = {
    "1": [[2], 10, 11, 8, 15, [ 40, 60, 120, 150], 0.2],
    "2": [[7], 15, 11, 8, 15, [20, 30, 40], 0.5],
    "3": [[0], 11, 11, 8, 15, [30,40, 55], 0],
    "4": [[2], 15, 15, 8, 15, [10, 20, 40], 0],
    "5": [[1], 15, 15, 8, 15, [20, 40, 60, 80], 0.1],
    "6":[[0], 15, 15, 8, 15, [5, 10, 20, 40, 55], 0]
    # "2": [[15, 120], 10, 11, 8, 15, [80, 40, 20], 0.5],
    # "4": [[4], 10, 11, 8, 20, [10,20,30,40], 0.3],
}

calcArgsFanzhuan = {
    "1": [[2], 10, 11, 8, 18, [20, 40, 60, 120], 0.2],
    "2": [[5], 17, 11, 8, 15, [10, 20, 30, 40], 0.5],
    "3": [[0], 17, 17, 8, 15, [3, 5, 10, 20, 40, 55], 0],
    "4": [[2], 17, 17, 8, 15, [5, 10, 20, 40], 0],
    "5": [[8], 17, 17, 8, 15, [1, 2, 5, 10], 0],
    "6": [[2], 17, 17, 8, 20, [20, 40, 60, 80], 0.2],
    # "2": [[15, 120], 10, 11, 8, 15, [80, 40, 20], 0.5],
    # "4": [[4], 10, 11, 8, 20, [10,20,30,40], 0.3],
}


def image_show(name, image, showState=False):
    """
    显示图片,用来调试的时候显示图片,按照一定的比例进行缩放
    :param name:显示的图片窗口名称
    :param image:显示的图片
    :param showState:是否显示
    :return:
    """
    if showState:
        sizeScale = 4
        newWidth = int(image.shape[1] / sizeScale)
        newHeight = int(image.shape[0] / sizeScale)
        showImage = cv.resize(image, (newWidth, newHeight), cv.INTER_AREA)
        cv.namedWindow("{}".format(name))
        cv.imshow("{}".format(name), showImage)
        cv.waitKey(0)


def find_total_board(image, width, height):
    """
    找到板子的整个物料区域
    :param image: 图像
    :param width: 物料宽
    :param height: 物料高
    :return:
    """
    # 1.先进行阈值分割
    thresUsed = np.mean(image[50:250, 100:1100]) + 15
    filterArea = 4500
    T, board = cv.threshold(image, thresUsed, 255, cv.THRESH_BINARY)
    cnts = cv.findContours(board.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    cnts = sorted(cnts, key=cv.contourArea, reverse=True)

    # 2.然后将找到的所有的满足条件的区域,通过白线连接起来,形成整个物料框
    largeContours = [cnt for cnt in cnts if cv.contourArea(cnt) > filterArea]
    if len(largeContours) >= 2:
        centerPoints = [get_center_by_contour(contour) for contour in largeContours]
        for index, center in enumerate(centerPoints):
            anotherCenter = centerPoints[(index + 1) % len(centerPoints)]
            cv.line(board, center, anotherCenter, 255, 20)
        image_show("JointCenterLine", board)

        # 3.连线之后再找一遍
        cnts = cv.findContours(board.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntsFirstFinded = sorted(cnts, key=cv.contourArea, reverse=True)[0]
    else:
        cntsFirstFinded = largeContours[0]

    # 4.这个轮廓找到以后,将这个轮廓的四个角的影响去除掉
    rectPoints = np.int0(cv.boxPoints(cv.minAreaRect(cntsFirstFinded)))
    leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectPoints)

    # 5.去掉物料区域的四个角,再找一次,这里的宽高,应该用整个物料的尺寸去做
    totalWidth = distance(leftTop, rightTop)
    totalHeight = distance(leftTop, leftBottom)
    boardFinal = cv.drawContours(image.copy(), [cntsFirstFinded], -1, 255, -1)
    image_show("BoardFinalUsed", boardFinal)
    moveWidth = int(totalWidth * 0.01)
    moveHeight = int(totalHeight * 0.1)
    extend = 20

    boardFinal[leftTop[1] - extend:leftTop[1] + moveHeight, leftTop[0] - extend:leftTop[0] + moveWidth] = 0
    boardFinal[rightTop[1] - extend:rightTop[1] + moveHeight, rightTop[0] - moveWidth:rightTop[0] + extend] = 0
    boardFinal[leftBottom[1] - moveHeight:leftBottom[1] + extend, leftBottom[0] - extend:leftBottom[0] + moveWidth] = 0
    boardFinal[rightBottom[1] - moveHeight:rightBottom[1] + extend,
    rightBottom[0] - moveWidth:rightBottom[0] + extend] = 0
    image_show("FinalBoardAngleMoved", boardFinal)

    T, board = cv.threshold(boardFinal, thresUsed, 255, cv.THRESH_BINARY)
    image_show("FinalBoardThres", board)

    cnts = cv.findContours(board.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    largeContours = [cnt for cnt in cnts if cv.contourArea(cnt) > filterArea]

    if len(largeContours) >= 2:
        centerPoints = [get_center_by_contour(contour) for contour in largeContours]
        for index, center in enumerate(centerPoints):
            anotherCenter = centerPoints[(index + 1) % len(centerPoints)]
            cv.line(board, center, anotherCenter, 255, 20)
        image_show("JointCenterLine", board)

        # 6.连线之后再找一遍
        cnts = cv.findContours(board.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntFinalFinded = sorted(cnts, key=cv.contourArea, reverse=True)[0]
    else:
        cntFinalFinded = largeContours[0]

    totalBoardThres = board.copy()
    cv.drawContours(totalBoardThres, cntFinalFinded, -1, 255, -1)
    image_show("TotalBoardThres", totalBoardThres)
    box = cv.minAreaRect(cntFinalFinded)
    (cx, cy), (w, h), angle = box
    if angle > 70:
        angle = 90 - angle
        box = (cx, cy), (h, w), angle
    elif angle < -70:
        angle = 90 + angle
        box = (cx, cy), (h, w), angle
    rectPoints = np.int0(cv.boxPoints(box))
    imageColor = cv.cvtColor(image, cv.COLOR_GRAY2BGR)
    boxMask = np.zeros(image.shape, dtype=np.uint8)
    cv.drawContours(boxMask, [rectPoints], -1, 255, -1)
    cv.drawContours(imageColor, [rectPoints], -1, (0, 255, 0), 2)
    image_show("TotalBoard", imageColor)
    return box, totalBoardThres, imageColor


def put_table_sensor_pos_to_image(totalBoardRes, tableVal, sensorVal):
    """
    将选取的传感器位置和台布位置画到图上去.
    :param totalBoardRes: 返回的找到的物料区域的图像.
    :param tableVal: 台布的亮度均值
    :param sensorVal: 传感器的亮度均值
    :return:返回totalBoard加上传感器位置和台布位置信息的图像
    """
    tablePoints = [(cp.tablePosStart, cp.sensorPos - 100),
                   (cp.tablePosEnd, cp.sensorPos - 100),
                   (cp.tablePosEnd, cp.sensorPos),
                   (cp.tablePosStart, cp.sensorPos)]

    sensorPoints = [(cp.tablePosStart, cp.sensorPos),
                    (cp.tablePosEnd, cp.sensorPos),
                    (cp.tablePosEnd, cp.sensorPos + 100),
                    (cp.tablePosStart, cp.sensorPos + 100)]

    tableCenter = get_two_points_middle(tablePoints[0], tablePoints[1])
    sensorCenter = get_two_points_middle(sensorPoints[2], sensorPoints[3])

    # 画上框 和 下框,以及计算的值
    cv.drawContours(totalBoardRes, [np.array(tablePoints)], -1, (255, 0, 0), 3)
    cv.drawContours(totalBoardRes, [np.array(sensorPoints)], -1, (0, 0, 255), 3)
    cv.putText(totalBoardRes, str(tableVal), (int(tableCenter[0]), int(tableCenter[1] - 20)), cv.FONT_HERSHEY_COMPLEX, 2,
               (255, 0, 0))
    cv.putText(totalBoardRes, str(sensorVal), (int(sensorCenter[0]), int(sensorCenter[1] + 50)), cv.FONT_HERSHEY_COMPLEX,
               2, (0, 0, 255))
    image_show("TotalBoardTableVal", totalBoardRes)
    return totalBoardRes


def get_first_check_result(image, width, height, calcThresBig, totalBoardBox, isFanzhuan="否"):
    """
     尺寸确认这里调用的代码逻辑,然后算子使用的是什么算子呢,算子保存到configParams里面.
    :param image:出入的图片
    :param width:要找的内板的宽
    :param height:内板的高
    :param calcThresBig:偏大阈值
    :param totalBoardBox:整个物料框的位置
    :return:
    """
    print("in get_first_check_result()!")
    if image is None:
        return "error", "图像异常,请重拍", None, None, None
    totalBoard = get_board_widthout_angle(image, totalBoardBox)
    jointLineMask = np.ones(image.shape, dtype=np.uint8) * 255
    jointLineMask[:, cp.middleJointPos - jointLineFillSize:cp.middleJointPos + jointLineFillSize] = 0  # 中缝拼接处的处理
    jointLineMaskRotated = get_board_widthout_angle(jointLineMask, totalBoardBox)
    jointLineMask2 = np.zeros(image.shape, dtype=np.uint8)
    jointLineMask2[:, cp.middleJointPos - jointLineFillSize:cp.middleJointPos + jointLineFillSize] = 255  # 中缝拼接处的处理
    jointLineMaskRotated2 = get_board_widthout_angle(jointLineMask2, totalBoardBox)
    image_show("TotalBoard", totalBoard)

    _, (w, h), angle = totalBoardBox
    heightHalf = int(h / 2)
    # 先将图片分成两幅图
    upBoard = totalBoard.copy()[:int(heightHalf + upDownSlice), :]
    upBoardColor = cv.cvtColor(upBoard, cv.COLOR_GRAY2BGR)
    upJointLine = jointLineMaskRotated.copy()[:int(heightHalf + upDownSlice), :]
    upJointLine2 = jointLineMaskRotated2.copy()[:int(heightHalf + upDownSlice), :]

    upRes, upSizes, upBoxes = get_size_check_inner_board_info(upBoard, upJointLine, upJointLine2, width, height, calcThresBig, isFanzhuan)
    upBoardResList = []
    upSizeResList = []
    if upRes == "ok":
        for index, upBox in enumerate(upBoxes):
            if upBox is not None:
                upBoardRes = upBoardColor.copy()
                cv.putText(upBoardRes, "{}".format(index + 1),
                           (int(upBoardColor.shape[1] / 2 - 8), int(upBoardColor.shape[1] / 2)),
                           cv.FONT_HERSHEY_COMPLEX, 10, (255, 0, 0))
                cv.drawContours(upBoardRes, [np.array(upBox)], -1, (0, 255, 0), 2)
                image_show("upBoardRes", upBoardRes)
                upBoardResList.append(upBoardRes)
                upSizeResList.append(upSizes[index])
        return "ok", upSizeResList, upBoardResList, upBoardColor
    else:
        return "error", "内板识别出错", None, upBoardColor


def get_boxes(image, width, height, calcBig, calcSmall, innerEdgeThres, totalBoardBox, boardThresWithAngle,
              upLineOffset, downLineOffset, isFanzhuan="否"):
    """
    正常的板获取内框图
    :param image: 原图
    :param width: 宽
    :param height: 高
    :param calcBig: 偏大阈值
    :param calcSmall: 偏小阈值
    :param innerEdgeThres: 位置正确阈值
    :param totalBoardBox: 整个物料框的位置信息
    :param boardThresWithAngle: board二值化有角度的
    :param upLineOffset: 上框的位置信息
    :param downLineOffset: 下框的位置信息
    :return:
    """
    print("in get_boxes()")
    _, (w, h), _ = totalBoardBox
    heightHalf = int(h / 2)
    totalBoard = get_board_widthout_angle(image, totalBoardBox)
    totalBoardColor = cv.cvtColor(totalBoard, cv.COLOR_GRAY2BGR)
    jointLineMask = np.ones(image.shape, dtype=np.uint8) * 255
    jointLineMask[:, cp.middleJointPos - jointLineFillSize:cp.middleJointPos + jointLineFillSize] = 0  # 中缝拼接处的处理
    jointLineMaskRotated = get_board_widthout_angle(jointLineMask, totalBoardBox)

    jointLineMask2 = np.zeros(image.shape, dtype=np.uint8)
    jointLineMask2[:, cp.middleJointPos - jointLineFillSize:cp.middleJointPos + jointLineFillSize] = 255  # 中缝拼接处的处理
    jointLineMaskRotated2 = get_board_widthout_angle(jointLineMask2, totalBoardBox)
    totalBoardThres = get_board_widthout_angle(boardThresWithAngle, totalBoardBox)
    image_show("TotalBoard", totalBoard)
    upDownSlice = int(50 * cp.mm2pix)
    upBoard = totalBoard.copy()[:int(heightHalf + upDownSlice), :]
    downBoard = totalBoard.copy()[int(heightHalf - upDownSlice):, :]
    upJointLine = jointLineMaskRotated.copy()[:int(heightHalf + upDownSlice), :]
    downJointLine = jointLineMaskRotated.copy()[int(heightHalf - upDownSlice):, :]
    upJointLine2 = jointLineMaskRotated2.copy()[:int(heightHalf + upDownSlice), :]
    downJointLine2 = jointLineMaskRotated2.copy()[int(heightHalf - upDownSlice):, :]

    # 根据这两个框分别去去它的信息
    upRes, upInfo, upBox = get_inner_board_info(upBoard, upJointLine, upJointLine2, width, height, calcBig, calcSmall, innerEdgeThres,
                                                "up", upLineOffset, isFanzhuan, upBox=None, heightHalf=heightHalf)
    downRes, downInfo, downBox = get_inner_board_info(downBoard, downJointLine, downJointLine2, width, height, calcBig, calcSmall,
                                                      innerEdgeThres,
                                                      "down", downLineOffset, isFanzhuan, upBox=upBox, heightHalf=heightHalf)
    if upRes == "ok" and downRes == "ok":
        downBoxPoints = [(p[0], p[1] + heightHalf - upDownSlice) for p in downBox]
        cv.drawContours(totalBoardColor, [np.array(upBox), np.array(downBoxPoints)], -1, (0, 255, 0), 2)
        image_show("TwoBoxes", totalBoardColor)
        downBox = downBoxPoints
        return True, "", upBox, downBox, totalBoard, totalBoardThres
    elif upRes == "sizeDif" or downRes == "sizeDif":
        return False, upInfo + downInfo, upBox, downBox, totalBoard, totalBoardThres
    else:
        return False, upInfo + downInfo, upBox, downBox, totalBoard, totalBoardThres


def get_boxes_first(image, width, height, calcBig, calcSmall, totalBoardBox, boardThresWithAngle, isFanzhuan):
    """
    首板的时候,进行识别,获取识别的内框,这个地方进行识别的时候,注意是没有板的尺寸位置信息的.
    :param image:
    :param width:
    :param height:
    :param calcBig:
    :param calcSmall:
    :param totalBoardBox:
    :param boardThresWithAngle:
    :return:
    """
    print("in get_boxes_first()")
    _, (w, h), _ = totalBoardBox
    heightHalf = int(h / 2)
    totalBoard = get_board_widthout_angle(image, totalBoardBox)
    totalBoardColor = cv.cvtColor(totalBoard, cv.COLOR_GRAY2BGR)
    jointLineMask = np.ones(image.shape, dtype=np.uint8) * 255
    jointLineMask[:, cp.middleJointPos - jointLineFillSize:cp.middleJointPos + jointLineFillSize] = 0  # 中缝拼接处的处理
    jointLineMaskRotated = get_board_widthout_angle(jointLineMask, totalBoardBox)

    jointLineMask2 = np.zeros(image.shape, dtype=np.uint8)
    jointLineMask2[:, cp.middleJointPos - jointLineFillSize:cp.middleJointPos + jointLineFillSize] = 255  # 中缝拼接处的处理
    jointLineMaskRotated2 = get_board_widthout_angle(jointLineMask2, totalBoardBox)

    totalBoardThres = boardThresWithAngle.copy()
    image_show("TotalBoard", totalBoard)

    upDownSlice = int(50 * cp.mm2pix)
    upBoard = totalBoard.copy()[:int(heightHalf + upDownSlice), :]
    downBoard = totalBoard.copy()[int(heightHalf - upDownSlice):, :]
    upJointLine = jointLineMaskRotated.copy()[:int(heightHalf + upDownSlice), :]
    downJointLine = jointLineMaskRotated.copy()[int(heightHalf - upDownSlice):, :]
    upJointLine2 = jointLineMaskRotated2.copy()[:int(heightHalf + upDownSlice), :]
    downJointLine2 = jointLineMaskRotated2.copy()[int(heightHalf - upDownSlice):, :]

    # 根据这两个框分别去去它的信息
    upRes, upInfo, upBox = get_inner_board_info_first(upBoard, upJointLine, upJointLine2, width, height, calcBig, calcSmall, "up",
                                                      isFanzhuan=isFanzhuan, upBox=None, heightHalf=heightHalf)
    downRes, downInfo, downBox = get_inner_board_info_first(downBoard, downJointLine, downJointLine2, width, height, calcBig, calcSmall,
                                                            "down", isFanzhuan=isFanzhuan, upBox=upBox, heightHalf=heightHalf)
    if upRes == "ok" and downRes == "ok":
        downBoxPoints = [(p[0], p[1] + heightHalf - upDownSlice) for p in downBox]
        cv.drawContours(totalBoardColor, [np.array(upBox), np.array(downBoxPoints)], -1, (0, 255, 0), 2)
        image_show("TwoBoxes", totalBoardColor)
        downBox = downBoxPoints
        return True, "识别ok", upBox, downBox, totalBoard, totalBoardThres
    elif upRes == "sizeDif" or downRes == "sizeDif":
        return False, upInfo + downInfo, upBox, downBox, totalBoard, totalBoardThres
    else:
        return False, upInfo + downInfo, upBox, downBox, totalBoard, totalBoardThres


def get_inner_board_info(board, jointLine, jointLine2, width, height, calcBig, calcSmall, innerEdgeThres, boardPos, lineOffset, isFanzhuan, upBox,
                         heightHalf):
    """
    正常非首板识别的时候找内框的逻辑
    :param board:
    :param jointLine:
    :param width:
    :param height:
    :param calcBig:
    :param calcSmall:
    :param innerEdgeThres:
    :param boardPos:
    :param lineOffset:
    :return:
    """
    imageHeight, imageWidth = height, width
    moveWidth = int(imageWidth * 0.25)
    moveHeight = int(imageHeight * 0.25)
    boardColor = cv.cvtColor(board.copy(), cv.COLOR_GRAY2BGR)
    sizeOkRes = []
    sizeOkByExtendRes = []
    sizeDifRes = []
    if isFanzhuan == "否":
        calcArgs = calcArgsNormal
    else:
        calcArgs = calcArgsFanzhuan
    res = {
        "info": "",
        "box": None,
    }
    # 算子打印出来
    print("使用的算子:")
    for tryTimes in range(1, len(calcArgs.keys()) + 1):
        print("{} : {}".format(str(tryTimes), calcArgs.get(str(tryTimes))))
    for tryTimes in range(tryBeginIndex, len(calcArgs.keys()) + 1):
        cv.destroyAllWindows()
        gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate = calcArgs.get(str(tryTimes))
        print("进行第{}次计算,计算参数:(高斯半径:{}),(方差核大小:{}),(膨胀腐蚀核:{}),(膨胀腐蚀次数:{}),(腐蚀膨胀次数:{}),(阈值offset:{}),(scharr比例:{})".format(
            tryTimes, gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate))
        if len(gaussianR) == 1:
            if gaussianR[0] == 0:
                blurred = board.copy()
            else:
                blurred = cv.GaussianBlur(board, (0, 0), gaussianR[0])
        else:
            d, colorSigma = gaussianR
            spaceSigma = int(d / 2)
            blurred = cv.bilateralFilter(board, d, colorSigma, spaceSigma)

        if scharrRate == 0:
            scharrXY = blurred.copy()
        else:
            scharrX = cv.Scharr(blurred, cv.CV_64F, 1, 0)
            scharrY = cv.Scharr(blurred, cv.CV_64F, 0, 1)
            scharrX = cv.convertScaleAbs(scharrX)
            scharrY = cv.convertScaleAbs(scharrY)
            scharrXY = cv.addWeighted(scharrX, scharrRate, scharrY, scharrRate, 0)
            scharrXY = cv.bitwise_and(scharrXY, jointLine)
        image_show("ScharrXY", scharrXY)
        img32 = np.float32(scharrXY)
        square1 = cv.blur(np.multiply(img32, img32), (squareR, squareR))
        square2 = np.multiply(cv.blur(img32, (squareR, squareR)), cv.blur(img32, (squareR, squareR)))
        squareDif32 = np.subtract(square1, square2)
        squareDif = squareDif32.copy()
        np.clip(squareDif32, 0, 255, out=squareDif)
        squareDif = squareDif.astype("uint8")
        image_show("SquareDif", squareDif)

        # 1.进行膨胀腐蚀,分割图像
        contourImg = squareDif.copy()
        kernelUsed = cv.getStructuringElement(cv.MORPH_RECT, (dilateKernel, dilateKernel))
        contourImg = cv.dilate(contourImg, kernelUsed, iterations=dilateTimes)
        contourImg = cv.erode(contourImg, kernelUsed, iterations=dilateTimes)
        image_show("squareDifDilateErode", contourImg)

        squareDifErode = contourImg.copy()
        for index, thresOffset in enumerate(thresOffsetList):
            cv.destroyAllWindows()
            image_show("squareDifDilateErode", squareDifErode)
            # 2. 根据阈值进行分割
            thresUsed = squareDifErode[moveHeight:int(contourImg.shape[0] - moveHeight),
                        moveWidth:contourImg.shape[1] - moveWidth]
            print("第{}个阈值,使用阈值 = {},thresOffset = {}".format(index + 1, np.mean(thresUsed), thresOffset))
            _, contourImg = cv.threshold(squareDifErode, np.mean(thresUsed) + thresOffset, 255, cv.THRESH_BINARY)

            # 3. 处理拼接处,提前处理
            if scharrRate == 0:
                contourImg = cv.subtract(contourImg, jointLine2)

            # 4. 进行泛洪填充
            mask = np.zeros((contourImg.shape[0] + 2, contourImg.shape[1] + 2), dtype=np.uint8)
            if contourImg[contourImg.shape[0] // 2, contourImg.shape[1] // 2] < 150:
                cv.floodFill(contourImg, mask, (contourImg.shape[1] // 2, contourImg.shape[0] // 2), 150)
            else:
                cv.floodFill(contourImg, mask, (contourImg.shape[1] // 3, contourImg.shape[0] // 3), 150)
            floodFill = np.zeros(contourImg.shape, dtype=np.uint8)
            floodFill[contourImg == 150] = 250
            image_show("FloodFill", floodFill)

            # 5.进行腐蚀膨胀,去除掉边界的噪点
            floodFill = cv.erode(floodFill, kernelUsed, iterations=erodeTimes)
            floodFill = cv.dilate(floodFill, kernelUsed, iterations=erodeTimes)
            image_show("FloodFillErodeDilate", floodFill)

            if (len(gaussianR) == 1 and gaussianR[0] >= 8 and isFanzhuan == "否") or (len(gaussianR) == 1 and gaussianR[0] >= 8 and isFanzhuan == "是"):
                innerLine = True
            else:
                innerLine = False

            if tryTimes == 2:
                extendMiddle = True
            else:
                extendMiddle = False

            res = check_inner_board(floodFill, width, height, calcBig, calcSmall, innerEdgeThres, boardPos, lineOffset,
                                    boardColor, innerLine, extendMiddle, upBox, heightHalf)
            print("计算结果:{},信息:{},尺寸:{},{},误差:{}".format(res["result"], res["info"], res["calcSize"],
                                                        (int(res["calcSize"][0] * cp.mm2pix),
                                                         int(res["calcSize"][1] * cp.mm2pix)),
                                                        res["calcError"]))
            if res["result"] == "ok":
                sizeOkRes.append(res)
                if int(np.sum([abs(res["calcError"][0]), abs(res["calcError"][1])])) < 8:  # 如果不是做首片,并且阈值小于8个mm,就直接返回.
                    print("返回的ok结果是,尺寸:{},{},误差:{}".format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                                             int(res["calcSize"][1] * cp.mm2pix)),
                                                           res["calcError"]))
                    return "ok", res["info"], res["box"]

            elif res["result"] == "okByExtend":
                sizeOkByExtendRes.append(res)
                continue
            elif res["result"] == "big" and not innerLine and not extendMiddle:
                sizeDifRes.append(res)
                break
            elif res["result"] == "small":
                sizeDifRes.append(res)
                continue
    else:
        if len(sizeOkRes) >= 1:
            resOkSorted = sorted(sizeOkRes, key=lambda x: np.sum([abs(x["calcError"][0]), abs(x["calcError"][1])]))
            res = resOkSorted[0]
            print("返回的ok结果是,尺寸:{},{},误差:{}".format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                                     int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
            return "ok", res["info"], res["box"]

        if len(sizeOkByExtendRes) >= 1:
            resOkSorted = sorted(sizeOkByExtendRes, key=lambda x: np.sum([abs(x["calcError"][0]), abs(x["calcError"][1])]))
            res = resOkSorted[0]
            print("返回的通过推测的ok结果,尺寸:{},{},误差:{}".format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                                         int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
            return "ok", res["info"], res["box"]

        if len(sizeDifRes) >= 1:
            resSorted = sorted(sizeDifRes, key=lambda x: np.sum([abs(x["calcError"][0]), abs(x["calcError"][1])]))
            res = resSorted[0]
            return "sizeDif", res["info"], res["box"]
        else:
            return "error", res["info"], res["box"]


def get_inner_board_info_first(board, jointLine, jointLine2, width, height, calcBig, calcSmall, boardPos, isFanzhuan="否", upBox=None,
                               heightHalf=None):
    """
    首片获取内板信息
    :param board:板子
    :param jointLine:拼接处
    :param width: 内板的宽
    :param height: 内板的高
    :param calcBig: 偏大阈值
    :param calcSmall: 偏小阈值
    :param boardPos: 板的位置,是上板还是下板
    :return:
    """
    imageHeight, imageWidth = height, width
    moveWidth = int(imageWidth * 0.25)
    moveHeight = int(imageHeight * 0.25)
    boardColor = cv.cvtColor(board.copy(), cv.COLOR_GRAY2BGR)
    sizeOkRes = []
    sizeDifRes = []
    sizeOkByExtendRes = []
    if isFanzhuan == "否":
        calcArgs = calcArgsNormal
    else:
        calcArgs = calcArgsFanzhuan
    res = {
        "info": "",
        "box": None,
    }
    # 算子打印出来
    print("使用的算子:")
    for tryTimes in range(1, len(calcArgs.keys()) + 1):
        print("{} : {}".format(str(tryTimes), calcArgs.get(str(tryTimes))))
    for tryTimes in range(tryBeginIndex, len(calcArgs.keys()) + 1):
        noMiddleCountTimes = 0
        cv.destroyAllWindows()
        gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate = calcArgs.get(str(tryTimes))
        print("进行第{}次计算,计算参数:(高斯半径:{}),(方差核大小:{}),(膨胀腐蚀核:{}),(膨胀腐蚀次数:{}),(腐蚀膨胀次数:{}),(阈值offset:{}),(scharr比例:{})".format(
            tryTimes, gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate))
        if len(gaussianR) == 1:
            if gaussianR[0] == 0:
                blurred = board.copy()
            else:
                blurred = cv.GaussianBlur(board, (0, 0), gaussianR[0])
        else:
            d, colorSigma = gaussianR
            spaceSigma = int(d / 2)
            blurred = cv.bilateralFilter(board, d, colorSigma, spaceSigma)

        if scharrRate == 0:
            scharrXY = blurred.copy()
        else:
            scharrX = cv.Scharr(blurred, cv.CV_64F, 1, 0)
            scharrY = cv.Scharr(blurred, cv.CV_64F, 0, 1)
            scharrX = cv.convertScaleAbs(scharrX)
            scharrY = cv.convertScaleAbs(scharrY)
            scharrXY = cv.addWeighted(scharrX, scharrRate, scharrY, scharrRate, 0)
        scharrXY = cv.bitwise_and(scharrXY, jointLine)
        image_show("ScharrXY", scharrXY)
        img32 = np.float32(scharrXY)
        square1 = cv.blur(np.multiply(img32, img32), (squareR, squareR))
        square2 = np.multiply(cv.blur(img32, (squareR, squareR)), cv.blur(img32, (squareR, squareR)))
        squareDif32 = np.subtract(square1, square2)
        squareDif = squareDif32.copy()
        np.clip(squareDif32, 0, 255, out=squareDif)
        squareDif = squareDif.astype("uint8")
        image_show("SquareDif", squareDif)

        # 1.进行膨胀腐蚀,分割图像
        contourImg = squareDif.copy()
        kernelUsed = cv.getStructuringElement(cv.MORPH_RECT, (dilateKernel, dilateKernel))
        contourImg = cv.dilate(contourImg, kernelUsed, iterations=dilateTimes)
        contourImg = cv.erode(contourImg, kernelUsed, iterations=dilateTimes)
        image_show("squareDifDilateErode", contourImg)

        squareDifErode = contourImg.copy()
        for index, thresOffset in enumerate(thresOffsetList):
            cv.destroyAllWindows()
            image_show("squareDifDilateErode", squareDifErode)
            # 2. 根据阈值进行分割
            thresUsed = squareDifErode[moveHeight:int(contourImg.shape[0] - moveHeight),
                        moveWidth:contourImg.shape[1] - moveWidth]
            print("第{}个阈值,使用阈值 = {},thresOffset = {}".format(index + 1, np.mean(thresUsed), thresOffset))
            _, contourImg = cv.threshold(squareDifErode, np.mean(thresUsed) + thresOffset, 255, cv.THRESH_BINARY)

            # # 3. 处理拼接处
            if scharrRate == 0:
                contourImg = cv.subtract(contourImg, jointLine2)
            # 4. 进行泛洪填充
            mask = np.zeros((contourImg.shape[0] + 2, contourImg.shape[1] + 2), dtype=np.uint8)
            if contourImg[contourImg.shape[0] // 2, contourImg.shape[1] // 2] < 150:
                cv.floodFill(contourImg, mask, (contourImg.shape[1] // 2, contourImg.shape[0] // 2), 150)
            else:
                cv.floodFill(contourImg, mask, (contourImg.shape[1] // 3, contourImg.shape[0] // 3), 150)
            floodFill = np.zeros(contourImg.shape, dtype=np.uint8)
            floodFill[contourImg == 150] = 250
            image_show("FloodFill", floodFill)

            # 5.进行腐蚀膨胀,去除掉边界的噪点
            floodFill = cv.erode(floodFill, kernelUsed, iterations=erodeTimes)
            floodFill = cv.dilate(floodFill, kernelUsed, iterations=erodeTimes)
            image_show("FloodFillErodeDilate", floodFill)
            if (len(gaussianR) == 1 and gaussianR[0] >= 8 and isFanzhuan == "否") or (len(gaussianR) == 1 and gaussianR[0] >= 8 and isFanzhuan == "是"):
                innerLine = True
            else:
                innerLine = False

            if tryTimes == 2:
                extendMiddle = True
            else:
                extendMiddle = False
            res = check_inner_board_for_first_board(floodFill, width, height, calcBig, calcSmall, boardPos,
                                                    boardColor, innerLine, extendMiddle, upBox, heightHalf)
            print("计算结果:{},info:{},尺寸:{},{},误差:{}".format(res["result"], res["info"], res["calcSize"],
                                                          (int(res["calcSize"][0] * cp.mm2pix),
                                                           int(res["calcSize"][1] * cp.mm2pix)),
                                                          res["calcError"]))
            if res["result"] == "ok":
                sizeOkRes.append(res)
                if int(np.sum([abs(res["calcError"][0]), abs(res["calcError"][1])])) < 7:  # 如果不是做首片,并且阈值小于8个mm,就直接返回.
                    print("返回的ok结果是,尺寸:{},{},误差:{}".format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                                             int(res["calcSize"][1] * cp.mm2pix)),
                                                           res["calcError"]))
                    return "ok", res["info"], res["box"]
            elif res["result"] == "okByExtend":
                sizeOkByExtendRes.append(res)
                continue
            elif res["result"] == "big" and not innerLine and not extendMiddle:
                sizeDifRes.append(res)
                break
            elif res["result"] == "small":
                sizeDifRes.append(res)
                continue
    else:
        if len(sizeOkRes) >= 1:
            resOkSorted = sorted(sizeOkRes, key=lambda x: np.sum([abs(x["calcError"][0]), abs(x["calcError"][1])]))
            res = resOkSorted[0]
            print("返回的ok结果是,尺寸:{},{},误差:{}".format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                                     int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
            return "ok", res["info"], res["box"]

        if len(sizeOkByExtendRes) >= 1:
            resOkSorted = sorted(sizeOkByExtendRes, key=lambda x: get_abs_sum(x["calcError"]))
            res = resOkSorted[0]
            print("返回的ok结果是,尺寸:{},{},误差:{}".format(res["calcSize"], (int(res["calcSize"][0] * cp.mm2pix),
                                                                     int(res["calcSize"][1] * cp.mm2pix)), res["calcError"]))
            return "ok", res["info"], res["box"]

        if len(sizeDifRes) >= 1:
            resSorted = sorted(sizeDifRes, key=lambda x: np.sum([abs(x["calcError"][0]), abs(x["calcError"][1])]))
            res = resSorted[0]
            return "sizeDif", res["info"], res["box"]
        else:
            return "error", res["info"], res["box"]


def get_size_check_inner_board_info(board, upJointLine, upJointLine2, width, height, calcThresBig, isFanzhuan):
    """
    首板尺寸确认的时候调用的代码逻辑.
    :param board:
    :param upJointLine:
    :param width:
    :param height:
    :param calcThresBig:
    :return:
    """
    imageHeight, imageWidth = height, width
    moveWidth = int(imageWidth * 0.25)
    moveHeight = int(imageHeight * 0.25)
    boardColor = cv.cvtColor(board.copy(), cv.COLOR_GRAY2BGR)
    sizeOkRes = []
    sizeDifRes = []
    sizeOkByExtendRes = []
    if isFanzhuan == "否":
        calcArgs = calcArgsNormal
    else:
        calcArgs = calcArgsFanzhuan
    boardPos = "up"
    # 算子打印出来
    print("使用的算子:")
    for tryTimes in range(1, len(calcArgs.keys()) + 1):
        print("{} : {}".format(str(tryTimes), calcArgs.get(str(tryTimes))))
    for tryTimes in range(tryBeginIndex, len(calcArgs.keys()) + 1):
        cv.destroyAllWindows()
        gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate = calcArgs.get(str(tryTimes))
        print("进行第{}次计算,计算参数:(高斯半径:{}),(方差核大小:{}),(膨胀腐蚀核:{}),(膨胀腐蚀次数:{}),(腐蚀膨胀次数:{}),(阈值offset:{}),(scharr比例:{})".format(
            tryTimes, gaussianR, squareR, dilateKernel, dilateTimes, erodeTimes, thresOffsetList, scharrRate))
        if len(gaussianR) == 1:
            if gaussianR[0] == 0:
                blurred = board.copy()
            else:
                blurred = cv.GaussianBlur(board, (0, 0), gaussianR[0])
        else:
            d, colorSigma = gaussianR
            spaceSigma = int(d / 2)
            blurred = cv.bilateralFilter(board, d, colorSigma, spaceSigma)

        if scharrRate == 0:
            scharrXY = blurred.copy()
        else:
            scharrX = cv.Scharr(blurred, cv.CV_64F, 1, 0)
            scharrY = cv.Scharr(blurred, cv.CV_64F, 0, 1)
            scharrX = cv.convertScaleAbs(scharrX)
            scharrY = cv.convertScaleAbs(scharrY)
            scharrXY = cv.addWeighted(scharrX, scharrRate, scharrY, scharrRate, 0)
            scharrXY = cv.bitwise_and(scharrXY, upJointLine)
        image_show("ScharrXY", scharrXY)
        img32 = np.float32(scharrXY)
        square1 = cv.blur(np.multiply(img32, img32), (squareR, squareR))
        square2 = np.multiply(cv.blur(img32, (squareR, squareR)), cv.blur(img32, (squareR, squareR)))
        squareDif32 = np.subtract(square1, square2)
        squareDif = squareDif32.copy()
        np.clip(squareDif32, 0, 255, out=squareDif)
        squareDif = squareDif.astype("uint8")
        image_show("SquareDif", squareDif)

        # 1.进行膨胀腐蚀,分割图像
        contourImg = squareDif.copy()
        kernelUsed = cv.getStructuringElement(cv.MORPH_RECT, (dilateKernel, dilateKernel))
        contourImg = cv.dilate(contourImg, kernelUsed, iterations=dilateTimes)
        contourImg = cv.erode(contourImg, kernelUsed, iterations=dilateTimes)
        image_show("squareDifDilateErode", contourImg)

        squareDifErode = contourImg.copy()
        for index, thresOffset in enumerate(thresOffsetList):

            cv.destroyAllWindows()
            image_show("squareDifDilateErode", squareDifErode)

            # 2. 根据阈值进行分割
            thresUsed = squareDifErode[moveHeight:int(contourImg.shape[0] - moveHeight),
                        moveWidth:contourImg.shape[1] - moveWidth]
            print("第{}个阈值,使用阈值 = {},thresOffset = {}".format(index + 1, np.mean(thresUsed), thresOffset))
            _, contourImg = cv.threshold(squareDifErode, np.mean(thresUsed) + thresOffset, 255, cv.THRESH_BINARY)

            # 3. 提前处理中缝拼接处
            if scharrRate == 0:
                contourImg = cv.subtract(contourImg, upJointLine2)
            # 4. 进行泛洪填充
            mask = np.zeros((contourImg.shape[0] + 2, contourImg.shape[1] + 2), dtype=np.uint8)
            print("FloodFillVal: {:.2f}".format(contourImg[contourImg.shape[0] // 2, contourImg.shape[1] // 2]))
            if contourImg[contourImg.shape[0] // 2, contourImg.shape[1] // 2] < 100:
                cv.floodFill(contourImg, mask, (contourImg.shape[1] // 2, contourImg.shape[0] // 2), 150)
            else:
                cv.floodFill(contourImg, mask, (contourImg.shape[1] // 3, contourImg.shape[0] // 3), 150)
            floodFill = np.zeros(contourImg.shape, dtype=np.uint8)
            floodFill[contourImg == 150] = 250
            image_show("FloodFill", floodFill)

            if (len(gaussianR) == 1 and gaussianR[0] >= 8 and isFanzhuan == "否") or (len(gaussianR) == 1 and gaussianR[0] >= 8 and isFanzhuan == "是"):
                innerLine = True
            else:
                innerLine = False

            if tryTimes == 2:
                extendMiddle = True
            else:
                extendMiddle = False

            # 5.进行腐蚀膨胀,去除掉边界的噪点
            floodFill = cv.erode(floodFill, kernelUsed, iterations=erodeTimes)
            floodFill = cv.dilate(floodFill, kernelUsed, iterations=erodeTimes)
            image_show("FloodFillErodeDilate", floodFill)
            res = check_inner_board_for_first_board(floodFill, width, height, calcThresBig, calcThresBig, boardPos, boardColor, innerLine,
                                                    extendMiddle)
            print("计算结果:{},info:{},尺寸:{},{},误差:{}".format(res["result"], res["info"], res["calcSize"],
                                                          (int(res["calcSize"][0] * cp.mm2pix),
                                                           int(res["calcSize"][1] * cp.mm2pix)),
                                                          res["calcError"]))
            if res["result"] == "ok":
                sizeOkRes.append(res)
                continue
            elif res["result"] == "okByExtend":
                sizeOkByExtendRes.append(res)
                continue
            elif res["result"] == "big" and not innerLine and not extendMiddle:
                sizeDifRes.append(res)
                break
            elif res["result"] == "small":
                sizeDifRes.append(res)
                continue
    else:
        sizeList = []
        boxList = []
        if len(sizeOkRes) >= 1:
            resOkSorted = sorted(sizeOkRes, key=lambda x: np.sum([abs(x["calcError"][0]), abs(x["calcError"][1])]))
            for res in resOkSorted:
                sizeList.append(res["calcSize"])
                boxList.append(res["box"])
            return "ok", sizeList, boxList
        # if len(sizeOkByExtendRes) >= 1:
        #     resOkSorted = sorted(sizeOkByExtendRes, key=lambda x: get_abs_sum(x["calcError"]))
        #     for res in resOkSorted:
        #         sizeList.append(res["calcSize"])
        #         boxList.append(res["box"])
        #     return "ok", sizeList, boxList

        if len(sizeDifRes) >= 1:
            resSizeDifList = sorted(sizeDifRes, key=lambda x: get_abs_sum(x["calcError"]))
            for res in resSizeDifList:
                sizeList.append(res["calcSize"])
                boxList.append(res["box"])
            return "sizeDif", sizeList, boxList
        else:
            return "error", "内板寻找失败", None


def get_abs_sum(it):
    """
    求一个序列的绝对值之和.因为算法的误差是宽和高,没有绝对值.所以带进来以后要求绝对值之和
    :param iterable:
    :return:
    """
    return sum([abs(x) for x in it])


def check_inner_board(board, width, height, calcThresBig, calcThresSmall, innerEdge, boardPos, lineOffset, boardColor, innerLine, extendMiddle, upBox,
                      heightHalf):
    """
    :param board:
    :param width:
    :param height:
    :param calcBig:
    :param calcSmall:
    :param innerEdge:
    :param boardPos:
    :param lineOffset:
    :param boardColor
    :return:
    """
    global minLineLength, maxLineGap, lineLengthMin
    useImage = boardColor.copy()
    boardArea = width * height
    totalHeightPix, totalWidthPix = board.shape[:2]
    totalWidthMm, totalHeightMm = round(totalWidthPix / cp.mm2pix, 2), round(totalHeightPix / cp.mm2pix, 2)
    moveWidth13 = int(totalWidthPix * 0.21)
    moveWidthMid = int(totalWidthPix * 0.3)
    moveHeight = int(totalHeightPix * 0.25)
    res = {
        "result": "error",
        "box": None,
        "info": "",
        "calcSize": (totalWidthMm, totalHeightMm),
        "calcError": (0, 0)
    }

    widthMax = width / cp.mm2pix + calcThresBig
    widthMin = width / cp.mm2pix - calcThresSmall
    heightMax = height / cp.mm2pix + calcThresBig
    heightMin = height / cp.mm2pix - calcThresSmall
    moveAngleUsed = board.copy()
    resByExtendFlag = False
    try:
        if boardPos == "up":
            cv.rectangle(moveAngleUsed, (0, 0), (moveWidth13, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1], 0), (moveAngleUsed.shape[1] - moveWidth13, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (0, moveAngleUsed.shape[0] - moveHeight), (moveWidthMid, moveAngleUsed.shape[0]), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1] - moveWidthMid, moveAngleUsed.shape[0] - moveHeight),
                         (moveAngleUsed.shape[1], moveAngleUsed.shape[0]), 0, -1)
        else:
            cv.rectangle(moveAngleUsed, (0, 0), (moveWidthMid, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1], 0), (moveAngleUsed.shape[1] - moveWidthMid, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (0, moveAngleUsed.shape[0] - moveHeight), (moveWidth13, moveAngleUsed.shape[0]), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1] - moveWidth13, moveAngleUsed.shape[0] - moveHeight),
                         (moveAngleUsed.shape[1], moveAngleUsed.shape[0]), 0, -1)

        image_show("MoveAngle", moveAngleUsed)

        cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
        if len(cnts) == 0:
            res["result"] = "error"
            res["box"] = [(0, 0), (0, 0), (0, 0), (0, 0)]
            res["info"] = "{} 框 找内板失败,没有找到任何的轮廓".format(boardPos)
            res["calcSize"] = (totalWidthMm, totalHeightMm)
            res["calcError"] = (round(totalWidthMm - width / cp.mm2pix, 2), round(totalHeightMm - height / cp.mm2pix))
            return res

        cntFindAgain = False  # 是否需要再找一遍轮廓
        _, (w, h), _ = cv.minAreaRect(cntsSorted[0])
        rectBox = cv.minAreaRect(cntsSorted[0])
        rectBoxPoints = np.int0(cv.boxPoints(rectBox))
        leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
        cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
        image_show("InnerBoardFinded", useImage)
        res["box"] = [leftTop, rightTop, rightBottom, leftBottom]
        widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
        heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)
        res["calcSize"] = (widthFinded, heightFinded)
        res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
        areaFinded = w * h
        if areaFinded < 0.7 * boardArea:
            res["result"] = "error"
            res["info"] = "{} 框 找内板失败,找到的内板面积过小".format(boardPos)
            return res
        elif boardArea > 1.4 * boardArea:
            res["result"] = "error"
            res["info"] = "{} 框 找内板失败,找到的内板的面积过大".format(boardPos)
        else:
            # 获取到物料边缘的距离
            line1 = [leftTop, rightTop]
            line2 = [rightTop, rightBottom]
            line3 = [rightBottom, leftBottom]
            line4 = [leftBottom, leftTop]

            line5 = [(0, 0), (totalWidthPix, 0)]
            line6 = [(totalWidthPix, 0), (totalWidthPix, totalHeightPix)]
            line7 = [(totalWidthPix, totalHeightPix), (0, totalHeightPix)]
            line8 = [(0, totalHeightPix), (0, 0)]

            offset1 = get_two_line_distance(line1, line5) / cp.mm2pix
            offset2 = get_two_line_distance(line2, line6) / cp.mm2pix
            offset3 = get_two_line_distance(line3, line7) / cp.mm2pix
            offset4 = get_two_line_distance(line4, line8) / cp.mm2pix

            print("offsetMm: {:.2f}, {:.2f}, {:.2f}, {:.2f}, offsetPix: {},{},{},{}".format(
                offset1, offset2, offset3, offset4, int(offset1 * cp.mm2pix), int(offset2 * cp.mm2pix),
                int(offset3 * cp.mm2pix), int(offset4 * cp.mm2pix)))
            if boardPos == "up":
                offset1Limit = 10
                offset3Limit = upDownSlice / cp.mm2pix - 15
            else:
                offset1Limit = upDownSlice / cp.mm2pix - 15
                offset3Limit = 10

            # 推测第一边
            if offset1 < offset1Limit and offset3 > offset3Limit:
                findLineBoard = board.copy()[:int(board.shape[0] * 0.4), :]
                image_show("boardUsedForLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.2, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeTop", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        lineLength = distance((x1, y1,), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle > 45):
                            continue
                        if boardPos == "up":
                            yMin = 10 * cp.mm2pix
                            yMax = board.shape[0] - height - 10 * cp.mm2pix
                        else:
                            yMin = 10 * cp.mm2pix
                            yMax = upDownSlice + 25 * cp.mm2pix
                        if abs(y2 - y1) < 10 * cp.mm2pix and abs(x2 - x1) > 5 * cp.mm2pix and yMin < y1 < yMax and \
                                yMin < y2 < yMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)

                if len(linesList) >= 2:
                    image_show("EdgeFindedTop", board1)
                    cntFindAgain = True
                    if boardPos == "up":
                        linesListFinal = sorted(linesList, key=lambda x: x[1])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[1], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    y1 = targetLine[0][1]
                    y2 = targetLine[1][1]
                    slicePos = int(min(y1, y2))  # 按照最小的那个去截取
                    moveAngleUsed[:slicePos, :] = 0
                    image_show("moveAngleAfterSliceTop", moveAngleUsed)

            # 如果第一边位置是对的,推测第三边
            if offset1 > offset1Limit and offset3 < offset3Limit:
                yOffset = int(board.shape[0] * 0.6)
                findLineBoard = board.copy()[yOffset:, :]
                image_show("boardUsedForLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.2, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeBottom", findLineBoard)

                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        y1 += yOffset
                        y2 += yOffset
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) > 45:
                            continue
                        if boardPos == "up":
                            yMin = board1.shape[0] - upDownSlice - 30 * cp.mm2pix
                            yMax = board1.shape[0] - upDownSlice + 10 * cp.mm2pix
                        else:
                            yMin = board1.shape[0] - 200 * cp.mm2pix
                            yMax = board1.shape[0] - 10 * cp.mm2pix

                        if abs(y2 - y1) < 10 * cp.mm2pix and abs(x2 - x1) > 5 * cp.mm2pix and yMin < y1 < yMax and \
                                yMin < y2 < yMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)

                if len(linesList) >= 2:
                    image_show("EdgeFindedBottom", board1)
                    cntFindAgain = True
                    if boardPos == "up":
                        linesListFinal = sorted(linesList, key=lambda x: x[1])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[1], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    y1 = targetLine[0][1]
                    y2 = targetLine[1][1]
                    slicePos = int(max(y1, y2))  # 按最大的那个去截取
                    moveAngleUsed[slicePos:, :] = 0
                    image_show("moveAngleAfterSliceBottom", moveAngleUsed)

            offset24Limit = 3
            # 如果第二边是对的,第四边是错误的,就证明第四边需要重新加载.
            if offset2 > 10 and offset4 < offset24Limit or innerLine and (widthFinded < widthMin or widthFinded > widthMax):
                findLineBoard = board.copy()[:, :int(board.shape[1] * 0.25)]
                image_show("boardUsed", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeLeft", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) < 45:
                            continue

                        xMin = 15 * cp.mm2pix
                        xMax = board1.shape[1] * 0.3
                        if boardPos == "up":
                            yMin = 10 * cp.mm2pix
                            yMax = board1.shape[0] - upDownSlice
                        else:
                            yMin = upDownSlice
                            yMax = board1.shape[0] - 10 * cp.mm2pix
                        if abs(x2 - x1) < 10 * cp.mm2pix and abs(y2 - y1) > 5 * cp.mm2pix and xMin < x1 < xMax and \
                                xMin < x2 < xMax and lineLength > lineLengthMin and yMin < y1 < yMax and yMin < y2 < yMax:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)
                if len(linesList) >= 2:
                    image_show("EdgeFindedLeft", board1)
                    cntFindAgain = True
                    if innerLine:
                        linesListFinal = sorted(linesList, key=lambda x: x[0], reverse=True)
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[0])
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    x1 = targetLine[0][0]
                    x2 = targetLine[1][0]
                    slicePos = int(min(x1, x2))
                    moveAngleUsed[:, :slicePos] = 0
                    image_show("moveAngleAfterSliceLeft", moveAngleUsed)

            if offset2 < offset24Limit and offset4 > 10 and (widthFinded < widthMin or widthFinded > widthMax):
                xOffset = int(board.shape[1] * 0.75)
                findLineBoard = board.copy()[:, xOffset:]
                image_show("boardUsed", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeLeft", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        x1 += xOffset
                        x2 += xOffset
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) < 45:
                            continue

                        xMin = board1.shape[1] * 0.7
                        xMax = board1.shape[1] - 15 * cp.mm2pix
                        if boardPos == "up":
                            yMin = 10 * cp.mm2pix
                            yMax = board1.shape[0] - upDownSlice
                        else:
                            yMin = upDownSlice
                            yMax = board1.shape[0] - 10 * cp.mm2pix
                        if abs(x2 - x1) < 10 * cp.mm2pix and abs(y2 - y1) > 5 * cp.mm2pix and xMin < x1 < xMax and \
                                xMin < x2 < xMax and lineLength > lineLengthMin and yMin < y1 < yMax and yMin < y2 < yMax:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)
                if len(linesList) >= 2:
                    image_show("EdgeFindedRight", board1)
                    cntFindAgain = True
                    if innerLine:
                        linesListFinal = sorted(linesList, key=lambda x: x[0])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[0], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    x1 = targetLine[0][0]
                    x2 = targetLine[1][0]
                    slicePos = int(max(x1, x2))
                    moveAngleUsed[:, slicePos:] = 0
                    image_show("moveAngleAfterSliceRight", moveAngleUsed)

            if cntFindAgain:
                resByExtendFlag = True
                cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
                cnts = imutils.grab_contours(cnts)
                cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
                rectBox = cv.minAreaRect(cntsSorted[0])
                rectBoxPoints = np.int0(cv.boxPoints(rectBox))
                useImage = boardColor.copy()
                cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
                image_show("InnerBoardFindedByFillEdgeZero", useImage)
                leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
                res["box"] = leftTop, rightTop, rightBottom, leftBottom
                widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
                heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)

            topLineAngle = get_angle_by_k(get_line_k(leftTop, rightTop))
            if abs(topLineAngle) > 18:
                res["result"] = "error"
                res["info"] = "识别的内框的第一边的角度太大,角度为: {:.2f}".format(topLineAngle)
                res["calcSize"] = (widthFinded, heightFinded)
                res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                return res

            # 再计算一次是否有错误的信息
            line1 = [leftTop, rightTop]
            line2 = [rightTop, rightBottom]
            line3 = [rightBottom, leftBottom]
            line4 = [leftTop, leftBottom]

            offset1 = get_two_line_distance(line1, line5) / cp.mm2pix
            offset2 = get_two_line_distance(line2, line6) / cp.mm2pix
            offset3 = get_two_line_distance(line3, line7) / cp.mm2pix
            offset4 = get_two_line_distance(line4, line8) / cp.mm2pix
            if min(offset1,offset3) < 8 or max(offset2,offset4) < 5:
                # 这里再看看是不是中缝的问题,如果中缝有问题,就推测中缝
                if boardPos == "up" and extendMiddle and offset1 > 10 and offset3 < 10:
                    # 推测上框的中缝
                    newBox = get_new_box_by_edge_and_width([leftTop, rightTop, rightBottom, leftBottom], height, boardPos, boardColor)
                    if newBox is not None:
                        resByExtendFlag = True
                        res["box"] = newBox
                        leftTop, rightTop, rightBottom, leftBottom = newBox
                        widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
                        heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)
                        res["calcSize"] = (widthFinded, heightFinded)
                        res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                        res["info"] = "识别成功,通过宽和第一边推测中缝"
                        useImg = boardColor.copy()
                        cv.drawContours(useImg, [np.array(newBox)], -1, (0, 255, 0), 3)
                        image_show("InnerBoardFindedByExtendForMiddle", useImg, 0, True)
                elif boardPos == "down" and extendMiddle and offset1 < 10 and offset3 > 10:
                    newBox = get_new_box_by_edge_and_width([leftTop, rightTop, rightBottom, leftBottom], height, boardPos,
                                                           boardColor)
                    if newBox is not None:
                        resByExtendFlag = True
                        res["box"] = newBox
                        leftTop, rightTop, rightBottom, leftBottom = newBox
                        widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
                        heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)
                        res["calcSize"] = (widthFinded, heightFinded)
                        res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                        res["info"] = "识别成功,通过宽和第三边推测中缝"
                        useImg = boardColor.copy()
                        cv.drawContours(useImg, [np.array(newBox)], -1, (0, 255, 0), 3)
                        image_show("InnerBoardFindedByExtendForMiddle", useImg, 0, True)
                else:
                    res["result"] = "big"
                    res["info"] = "识别的内框太靠近物料边缘: {:.2f},{:.2f},{:.2f},{:.2f}".format(offset1, offset2, offset3, offset4)
                    res["calcSize"] = (widthFinded, heightFinded)
                    res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                    return res

            res["calcSize"] = (widthFinded, heightFinded)
            res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))

            if widthFinded < widthMin or heightFinded < heightMin:
                if boardPos == "down" and heightFinded < heightMin and widthMin < widthFinded < widthMax:
                    middleLineY = get_two_points_middle(leftTop, rightTop)[1]
                    totalBoardY = 40 * cp.mm2pix
                    if (totalBoardY - middleLineY) > 7 * cp.mm2pix or (totalBoardY - middleLineY) < -20 * cp.mm2pix:
                        middleIsOk = False
                    else:
                        middleIsOk = True
                    if middleIsOk:
                        newBox = get_new_box_by_middle_and_width([leftTop, rightTop, rightBottom, leftBottom], height, boardPos,
                                                                 boardColor)
                        if newBox is not None:
                            res["box"] = newBox
                            resByExtendFlag = True
                            leftTop, rightTop, rightBottom, leftBottom = newBox
                            widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
                            heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)
                            res["calcSize"] = (widthFinded, heightFinded)
                            res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                            res["info"] = "识别成功,通过宽和中缝推测另外一边"
                            useImg = boardColor.copy()
                            cv.drawContours(useImg, [np.array(newBox)], -1, (0, 255, 0), 3)
                            image_show("InnerBoardFindedByExtend", useImg)
                        else:
                            res["result"] = "small"
                            res["info"] = "{} 框,识别的尺寸过小,识别尺寸:{}".format(boardPos, res["calcSize"])
                            return res
                    else:
                        res["result"] = "small"
                        res["info"] = "{} 框,识别的尺寸过小,识别尺寸:{}".format(boardPos, res["calcSize"])
                        return res
                else:

                    res["result"] = "small"
                    res["info"] = "{} 框,识别的尺寸过小,识别尺寸:{}".format(boardPos, res["calcSize"])
                    return res
            if widthFinded > widthMax or heightFinded > heightMax:
                res["result"] = "big"
                res["info"] = "{} 框,识别的尺寸过大,识别尺寸:{}".format(boardPos, res["calcSize"])
                return res

            boxFinded = res["box"]
            if boardPos == "down":
                downBoxPoints = [(p[0], p[1] + heightHalf - upDownSlice) for p in boxFinded]
                isOverlap = check_two_box_is_overlap(upBox, downBoxPoints)
                if isOverlap:
                    res["result"] = "error"
                    res["info"] = "上下框出现叠板,识别失败~"
                    return res

            # 检测一下左边和右边距离物料区域边缘的距离,如果误差在20个mm以上,就认为是错误的.
            leftCutLine = (leftTop, leftBottom)
            rightCutLine = (rightTop, rightBottom)
            leftBoardLine = ((0, 0), (0, board.shape[0]))
            rightBoardLine = ((board.shape[1], 0), (board.shape[1], board.shape[0]))
            leftOffset = get_two_line_distance(leftCutLine, leftBoardLine)
            rightOffset = get_two_line_distance(rightCutLine, rightBoardLine)
            leftRightLineOffsetMm = (leftOffset - rightOffset) / cp.mm2pix
            print("左右到物料边缘的误差: {:.1f}".format(leftRightLineOffsetMm))
            if abs(leftRightLineOffsetMm) > leftRightLineOffsetThres:
                res["result"] = "error"
                res["info"] = "识别的左右边框到物料边缘的距离差异太大,相差值: {:.1f},阈值:{}".format(leftRightLineOffsetMm,
                                                                             leftRightLineOffsetThres)
                widthFinded = distance(leftTop, rightTop)
                heightFinded = distance(leftTop, leftBottom)
                res["calcSize"] = (round(widthFinded / cp.mm2pix, 2), round(heightFinded / cp.mm2pix, 2))
                res["calcError"] = (
                    abs(round((widthFinded - width) / cp.mm2pix, 2)), abs(round((heightFinded - height) / cp.mm2pix)))
                return res

            if resByExtendFlag:
                res["result"] = "okByExtend"
            else:
                res["result"] = "ok"
                res["info"] = "识别成功!"
            return res

    except Exception as e:
        errorInfo = "in  check_inner_board() error: {}".format(str(e))
        print(errorInfo)
        res["result"] = "error"
        res["info"] = errorInfo
        res["calcSize"] = (totalWidthMm, totalHeightMm)
        res["calcError"] = (round(totalWidthMm - width / cp.mm2pix, 2), round(totalHeightMm - height / cp.mm2pix, 2))
        return res


# def other_line_is_ok():
#     useImage = boardColor.copy()
#     totalHeight, totalWidth = board.shape[:2]
#     boardArea = width * height
#     totalWidth = round(totalWidth / cp.mm2pix, 2)
#     totalHeight = round(totalHeight / cp.mm2pix, 2)
#     res = {
#         "result": "error",
#         "box": None,
#         "info": "",
#         "calcSize": (totalWidth, totalHeight),
#         "calcError": (0, 0),
#     }
#     cnts = cv.findContours(board.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
#     cnts = imutils.grab_contours(cnts)
#     cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
#     try:
#         _, (w, h), _ = cv.minAreaRect(cntsSorted[0])
#         areaFinded = w * h
#         if len(cnts) == 0:
#             res["result"] = "error"
#             res["info"] = "{} 找内板失败,没有找到任何轮廓".format(boardPos)
#             res["calcSize"] = (totalWidth, totalHeight)
#             res["calcError"] = (round(totalWidth - width / cp.mm2pix, 2), round(totalHeight - height / cp.mm2pix, 2))
#             return res
#         elif 1.3 * boardArea > areaFinded > 0.8 * boardArea:
#             rectBox = cv.minAreaRect(cntsSorted[0])
#             rectBoxPoints = np.int0(cv.boxPoints(rectBox))
#             cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
#             image_show("InnerBoardFinded", useImage)
#             leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
#             widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)  # 找到的宽,单位mm
#             heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)  # 找到的高,单位mm
#             widthError, heightError = round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2)
#             res["calcSize"] = (widthFinded, heightFinded)
#             res["calcError"] = (widthError, heightError)
#             # 过滤掉一定是错误的线.第一,如果找到的两个顶点
#             # 如果找到的第一边的一个顶点,太接近物料的顶点,就认为这条线肯定是找错了.
#
#             widthMax = width / cp.mm2pix + calcBig
#             widthMin = width / cp.mm2pix - calcSmall
#             heightMax = height / cp.mm2pix + calcBig
#             heightMin = height / cp.mm2pix - calcSmall
#             res["box"] = [leftTop, rightTop, rightBottom, leftBottom]
#             if widthFinded < widthMin or widthFinded > widthMax:
#                 otherLineIsOk, newBox = check_other_line_is_ok(board, res["box"], lineOffset, innerEdge, "13", width, boardPos)
#                 if otherLineIsOk:
#                     res["box"] = newBox
#                     leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(newBox)
#                     widthFinded = distance(leftTop, rightTop)
#                     heightFinded = distance(leftTop, leftBottom)
#                     res["calcSize"] = (round(widthFinded / cp.mm2pix, 2), round(heightFinded / cp.mm2pix, 2))
#                     res["calcError"] = (abs(round((widthFinded - width) / cp.mm2pix, 2)),
#                                         abs(round((heightFinded - height) / cp.mm2pix)))
#                     res["info"] = "识别成功,通过三边推测第三边"
#                     useImg = boardColor.copy()
#                     cv.drawContours(useImg, [np.array(newBox)], -1, (0, 255, 0), 3)
#                     image_show("InnerBoardFindedByExtend", useImg)
#
#                     res["result"] = "okByExtend"
#                     return res
#                 else:
#                     if widthFinded < widthMin:
#                         res["result"] = "small"
#                         res["info"] = "宽度识别过小,识别尺寸:({},{})".format(res["calcSize"][0], res["calcSize"][1])
#                         return res
#                     else:
#                         res["result"] = "big"
#                         res["info"] = "宽度识别过大,识别尺寸:({},{})".format(res["calcSize"][0], res["calcSize"][1])
#                         return res
#
#             if heightFinded < heightMin or heightFinded > heightMax:
#                 otherLineIsOk, newBox = check_other_line_is_ok(board, res["box"], lineOffset, innerEdge, "24", height, boardPos)
#                 if otherLineIsOk:
#                     res["box"] = newBox
#                     leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(newBox)
#                     widthFinded = distance(leftTop, rightTop)
#                     heightFinded = distance(leftTop, leftBottom)
#                     res["calcSize"] = (round(widthFinded / cp.mm2pix, 2), round(heightFinded / cp.mm2pix, 2))
#                     res["calcError"] = (abs(round((widthFinded - width) / cp.mm2pix, 2)),
#                                         abs(round((heightFinded - height) / cp.mm2pix)))
#                     res["info"] = "识别成功,通过三边推测第三边"
#                     useImg = boardColor.copy()
#                     cv.drawContours(useImg, [np.array(newBox)], -1, (0, 255, 0), 3)
#                     image_show("InnerBoardFindedByExtend", useImg)
#                     res["result"] = "okByExtend"
#                     return res
#                 else:
#                     if heightFinded < heightMin:
#                         res["result"] = "small"
#                         res["info"] = "高度识别过小,识别尺寸:({},{})".format(res["calcSize"][0], res["calcSize"][1])
#                         return res
#                     else:
#                         res["result"] = "big"
#                         res["info"] = "高度识别过大,识别尺寸:({},{})".format(res["calcSize"][0], res["calcSize"][1])
#                         if max(leftBottom[1], rightBottom[1]) > (totalHeight - 10) * cp.mm2pix and boardPos == "up":
#                             res["result"] = "noMiddle"
#                             res["info"] = "{}框 找到的内板中缝,太靠近下边缘,判定找板失败".format(boardPos)
#                             return res
#                         if get_two_points_middle(leftTop, rightTop)[1] < 8 * cp.mm2pix and boardPos == "down":
#                             res["result"] = "noMiddle"
#                             res["info"] = "{}框 找到的内板第三边,太靠近下边缘,判定找板失败".format(boardPos)
#                             return res
#                         return res
#
#             # 检测找到的边是否太靠近上边缘和下边缘
#             if get_two_points_middle(leftTop, rightTop)[1] < 8 * cp.mm2pix and boardPos == "up":
#                 res["result"] = "error"
#                 res["info"] = "{}框 找到的内板第一边,太靠近上边缘,判定找板失败".format(boardPos)
#                 return res
#
#             if max(leftBottom[1], rightBottom[1]) > (totalHeight - 10) * cp.mm2pix and boardPos == "up":
#                 res["result"] = "error"
#                 res["info"] = "{}框 找到的内板中缝,太靠近下边缘,判定找板失败".format(boardPos)
#                 return res
#
#             if min(leftTop[1], rightTop[1]) < 20 * cp.mm2pix and boardPos == "down":
#                 res["result"] = "error"
#                 res["info"] = "{}框 找到的内板第一边,太靠近上边缘,判定找板失败".format(boardPos)
#
#             if (leftBottom[1] + rightBottom[1]) / 2 > (totalHeight - 4) * cp.mm2pix and boardPos == "down":
#                 res["result"] = "error"
#                 res["info"] = "{}框 找到的内板第三边,太靠近下边缘,判定找板失败".format(boardPos)
#                 return res
#
#             res["result"] = "ok"
#             res["info"] = "{} 识别成功!".format(boardPos)
#             return res
#         else:
#             res["result"] = "error"
#             res["info"] = "识别的面积过大"
#             res["calcSize"] = (totalWidth, totalHeight)
#             res["calcError"] = (round(totalWidth - width / cp.mm2pix, 2), round(totalHeight - height / cp.mm2pix))
#             return res
#     except Exception as e:
#         errorInfo = "in check_inner_board() error:{}".format(str(e))
#         res["result"] = "error"
#         res["info"] = errorInfo
#         res["calcSize"] = (totalWidth, totalHeight)
#         res["calcError"] = (round(totalWidth - width / cp.mm2pix, 2), round(totalHeight - height / cp.mm2pix, 2))
#         return res


def get_line_offset(upBox, downBox, totalBoard, totalBoardBox):
    """
    获取识别的内框的offset,单位是像素
    :param upBox: 上框位置
    :param downBox: 下框位置
    :param totalBoard: 整个物料区域
    :param totalBoardBox: 整个物料区域的位置信息
    :return:
    """
    if len(totalBoard.shape) >= 3:
        totalBoard = cv.cvtColor(totalBoard, cv.COLOR_BGR2GRAY)
    w, h = totalBoardBox[1]
    heightHalf = int(h / 2)
    upDownSlice = int(50 * cp.mm2pix)
    upBoard = totalBoard.copy()[:int(heightHalf + upDownSlice), :]
    upH, upW = upBoard.shape[:2]
    p1 = (0, 0)
    p2 = (upW, 0)
    p3 = (upW, upH)
    p4 = (0, upH)
    p5, p6, p7, p8 = upBox
    line1, line2, line3, line4 = [(p1, p2), (p2, p3), (p3, p4), (p4, p1)]
    line5, line6, line7, line8 = [(p5, p6), (p6, p7), (p7, p8), (p8, p5)]
    offset1 = get_two_line_distance(line1, line5)
    offset2 = get_two_line_distance(line2, line6)
    offset3 = get_two_line_distance(line3, line7)
    offset4 = get_two_line_distance(line4, line8)
    upOffset = [int(offset1), int(offset2), int(offset3), int(offset4)]

    # 下框的额坐标也要是totalBoard上的坐标
    p1 = (0, heightHalf - upDownSlice)
    p2 = (w, heightHalf - upDownSlice)
    p3 = (w, h)
    p4 = (0, h)
    p5, p6, p7, p8 = downBox
    line1, line2, line3, line4 = [(p1, p2), (p2, p3), (p3, p4), (p4, p1)]
    line5, line6, line7, line8 = [(p5, p6), (p6, p7), (p7, p8), (p8, p5)]
    offset1 = get_two_line_distance(line1, line5)
    offset2 = get_two_line_distance(line2, line6)
    offset3 = get_two_line_distance(line3, line7)
    offset4 = get_two_line_distance(line4, line8)
    downOffset = [int(offset1), int(offset2), int(offset3), int(offset4)]
    return upOffset, downOffset


def get_new_box_for_no_middle(box, extend, boardPos):
    """
    根本板子的原来的位置信息,如果是上框,第一边,推测第三边中缝的位置.如果是下框,就是根据第三边推测第一边的位置.
    :param box:
    :param extend: 就是要延长的板的尺寸,这里一开始是使用高度进行延长
    :param boardPos:
    :return:
    """
    leftTop, rightTop, rightBottom, leftBottom = box
    leftK, leftB = get_line_k_and_b(leftTop, leftBottom)
    rightK, rightB = get_line_k_and_b(rightTop, rightBottom)
    if boardPos == "up":
        if leftK is None or rightK is None:
            newLeftBottom = [leftTop[0], leftTop[1] + extend]
            newRightBottom = [rightTop[0], rightTop[1] + extend]
            newLeftTop = leftTop
            newRightTop = rightTop
        else:
            yOffset = abs(extend * np.sin(trans_k_to_rad(leftK)))
            leftBottomY = int(leftTop[1] + yOffset)
            leftBottomX = int((leftBottomY - leftB) / leftK)
            rightBottomY = int(rightTop[1] + yOffset)
            rightBottomX = int((rightBottomY - rightB) / rightK)
            newLeftBottom = [leftBottomX, leftBottomY]
            newRightBottom = [rightBottomX, rightBottomY]
            newLeftTop = leftTop
            newRightTop = rightTop
    else:
        leftK, leftB = get_line_k_and_b(leftTop, leftBottom)
        rightK, rightB = get_line_k_and_b(rightTop, rightBottom)
        if leftK is None or rightK is None:
            newLeftTop = [leftTop[0], leftBottom[1] - extend]
            newRightTop = [rightTop[0], rightBottom[1] - extend]
            newLeftBottom = leftBottom
            newRightBottom = rightBottom
        else:
            yOffset = abs(extend * np.sin(trans_k_to_rad(leftK)))
            leftTopY = int(leftBottom[1] - yOffset)
            leftTopX = int((leftTopY - leftB) / leftK)
            rightTopY = int(rightBottom[1] - yOffset)
            rightTopX = int((rightTopY - rightB) / rightK)
            newLeftTop = [leftTopX, leftTopY]
            newRightTop = [rightTopX, rightTopY]
            newLeftBottom = leftBottom
            newRightBottom = rightBottom
    return [newLeftTop, newRightTop, newRightBottom, newLeftBottom]


def check_other_line_is_ok(board, box, lineOffset, innerEdge, checkPos, extend, boardPos):
    """
    检测其他的线是否OK
    :param board:
    :param box
    :param lineOffset:
    :param innerEdge:
    :param checkPos:检测的位置,13,表示检测13刀的位置,宽度检测有问题,这是时候去验证高度的距离位置是否在监控的范围内.如果再就通过延长线的方式重新画线.
    :param extend:切线需要延长的距离.
    :param boardPos, 是上框还是下框,主要是用来判定长铜箔的问题,如果是长铜箔就认为不是OK的.上框的时候是第一边,下框的时候是第三边
    :return:
    """
    extendErrorThres = 10
    longCropperMmLimit = 80  # 长铜箔不推测的mm限制,防止长铜箔折叠把板只遮挡起来
    h, w = board.shape[:2]
    p1 = (0, 0)
    p2 = (w, 0)
    p3 = (w, h)
    p4 = (0, h)
    p5, p6, p7, p8 = box
    line1, line2, line3, line4 = [(p1, p2), (p2, p3), (p3, p4), (p4, p1)]
    line5, line6, line7, line8 = [(p5, p6), (p6, p7), (p7, p8), (p8, p5)]
    offset1 = get_two_line_distance(line1, line5)
    offset2 = get_two_line_distance(line2, line6)
    offset3 = get_two_line_distance(line3, line7)
    offset4 = get_two_line_distance(line4, line8)
    innerEdge = innerEdge * cp.mm2pix
    offsetCheckVal = np.subtract(np.array(lineOffset), np.array([offset1, offset2, offset3, offset4])).tolist()
    offsetCheckVal = [abs(x) for x in offsetCheckVal]
    isOkList = [True if offsetCheck <= innerEdge else False for offsetCheck in offsetCheckVal]
    leftTop, rightTop, rightBottom, leftBottom = box
    if checkPos == "13":
        if isOkList[0] and isOkList[1] and isOkList[2]:
            # 这里过滤掉是长铜箔的情况
            if lineOffset[3] > longCropperMmLimit * cp.mm2pix:
                return False, box
            # 如果1,2,3的切线位置是对的,就推测第四条切线.顺时针方向的四条线1,2,3,4
            topK, topB = get_line_k_and_b(leftTop, rightTop)
            bottomK, bottomB = get_line_k_and_b(leftBottom, rightBottom)
            if topK == 0 or bottomK == 0:
                newLeftTop = [int(rightTop[0] - extend), rightTop[1]]
                newLeftBottom = [int(rightBottom[0] - extend), rightBottom[1]]
                newRightTop = rightTop
                newRightBottom = rightBottom
            else:
                xOffset = abs(extend * np.cos(trans_k_to_rad(topK)))  # 先将延长的距离,换算成x坐标的跨度.
                leftTopX = int(rightTop[0] - xOffset)
                leftTopY = int(topK * leftTopX + topB)
                leftBottomX = int(rightBottom[0] - xOffset)
                leftBottomY = int(bottomK * leftBottomX + bottomB)
                newLeftTop = [leftTopX, leftTopY]
                newLeftBottom = [leftBottomX, leftBottomY]
                newRightTop = rightTop
                newRightBottom = rightBottom
            # 判断推测出来的边和之前保存的是否误差在范围之内,这里推测的是第四边
            offset4New = get_two_line_distance(line4, (newLeftTop, newLeftBottom))
            extendOffsetError = (offset4New - lineOffset[3]) / cp.mm2pix  # 推测出来的板子的误差值
            print("推测的第四边的和首板的误差值: {:.2f}".format(extendOffsetError))
            if abs(extendOffsetError) < extendErrorThres:  # 如
                return True, [newLeftTop, newRightTop, newRightBottom, newLeftBottom]
            else:
                return False, box
        elif isOkList[0] and isOkList[2] and isOkList[3]:
            if lineOffset[1] > longCropperMmLimit * cp.mm2pix:
                return False, box
            # 如果1,3,4的切线是对的,就推测第2条线.顺时针方向的四条线1,2,3,4
            topK, topB = get_line_k_and_b(leftTop, rightTop)
            bottomK, bottomB = get_line_k_and_b(leftBottom, rightBottom)
            if topK == 0 or bottomK == 0:
                newRightTop = [int(leftTop[0] + extend), rightTop[1]]
                newRightBottom = [int(leftBottom[0] + extend), rightBottom[1]]
                newLeftTop = leftTop
                newLeftBottom = leftBottom
            else:
                xOffset = abs(extend * np.cos(trans_k_to_rad(topK)))  # 先将延长的距离,换算成x坐标的跨度.
                rightTopX = int(leftTop[0] + xOffset)
                rightTopY = int(topK * rightTopX + topB)
                rightBottomX = int(leftBottom[0] + xOffset)
                rightBottomY = int(bottomK * rightBottomX + bottomB)
                newRightTop = [rightTopX, rightTopY]
                newRightBottom = [rightBottomX, rightBottomY]
                newLeftTop = leftTop
                newLeftBottom = leftBottom
            offset2New = get_two_line_distance(line2, (newRightTop, newRightBottom))
            extendOffsetError = (offset2New - lineOffset[1]) / cp.mm2pix  # 推测出来的板子的误差值
            print("推测的第二边的和首板的误差值: {:.2f}".format(extendOffsetError))
            if abs(extendOffsetError) < extendErrorThres:  # 如果小于10个mm,就判断通过
                return True, [newLeftTop, newRightTop, newRightBottom, newLeftBottom]
            else:
                return False, box
        else:
            return False, box

    else:
        # 如果是调整高度的话.只考虑第一条边和第三条边,宽度这个时候已经检测通过了.不需要再去检测宽度的位置,推测完之后,再检查一遍
        if isOkList[0]:  # 推测第三边
            if lineOffset[2] > longCropperMmLimit * cp.mm2pix and boardPos == "down":
                return False, box
            leftK, leftB = get_line_k_and_b(leftTop, leftBottom)
            rightK, rightB = get_line_k_and_b(rightTop, rightBottom)
            if leftK is None or rightK is None:
                newLeftBottom = [leftTop[0], leftTop[1] + extend]
                newRightBottom = [rightTop[0], rightTop[1] + extend]
                newLeftTop = leftTop
                newRightTop = rightTop
            else:
                yOffset = abs(extend * np.sin(trans_k_to_rad(leftK)))
                leftBottomY = int(leftTop[1] + yOffset)
                leftBottomX = int((leftBottomY - leftB) / leftK)
                rightBottomY = int(rightTop[1] + yOffset)
                rightBottomX = int((rightBottomY - rightB) / rightK)
                newLeftBottom = [leftBottomX, leftBottomY]
                newRightBottom = [rightBottomX, rightBottomY]
                newLeftTop = leftTop
                newRightTop = rightTop
            offset3New = get_two_line_distance(line3, (newLeftBottom, newRightBottom))
            extendOffsetError = (offset3New - lineOffset[2]) / cp.mm2pix  # 推测出来的板子的误差值
            print("推测的第三边的和首板的误差值: {:.2f}".format(extendOffsetError))
            if abs(extendOffsetError) < extendErrorThres:  # 如果小于10个mm,就判断通过
                return True, [newLeftTop, newRightTop, newRightBottom, newLeftBottom]
            else:
                return False, box
        elif isOkList[2]:  # 推测第一边,只要对称边是对的就可以了
            if lineOffset[2] > longCropperMmLimit * cp.mm2pix and boardPos == "up":
                return False, box
            leftK, leftB = get_line_k_and_b(leftTop, leftBottom)
            rightK, rightB = get_line_k_and_b(rightTop, rightBottom)
            if leftK is None or rightK is None:
                newLeftTop = [leftTop[0], leftBottom[1] - extend]
                newRightTop = [rightTop[0], rightBottom[1] - extend]
                newLeftBottom = leftBottom
                newRightBottom = rightBottom
            else:
                yOffset = abs(extend * np.sin(trans_k_to_rad(leftK)))
                leftTopY = int(leftBottom[1] - yOffset)
                leftTopX = int((leftTopY - leftB) / leftK)
                rightTopY = int(rightBottom[1] - yOffset)
                rightTopX = int((rightTopY - rightB) / rightK)
                newLeftTop = [leftTopX, leftTopY]
                newRightTop = [rightTopX, rightTopY]
                newLeftBottom = leftBottom
                newRightBottom = rightBottom
            offset1New = get_two_line_distance(line1, (newLeftTop, newRightTop))
            extendOffsetError = (offset1New - lineOffset[0]) / cp.mm2pix  # 推测出来的板子的误差值
            print("推测的第一边的和首板的误差值: {:.2f}".format(extendOffsetError))
            if abs(extendOffsetError) < extendErrorThres:  # 如果小于10个mm,就判断通过
                return True, [newLeftTop, newRightTop, newRightBottom, newLeftBottom]
            else:
                return False, box
        else:
            return False, box


def get_angle_by_k(k):
    """
    根据斜率k值,获取对应的角度值
    :param k: 线条的斜率k值
    :return:
    """
    if k == 0:
        return 0
    if k is None:
        return 90
    return np.arctan(k) * 180 / np.pi


def check_inner_board_for_first_board(board, width, height, calcThresBig, calcThresSmall, boardPos, boardColor, innerLine, extendMiddle, upBox=None,
                                      heightHalf=None):
    """
    检查找到的内板,根据去角之后的图像.
    :param board: 最后处理掉的包含内板的二值图像
    :param width: 内板宽
    :param height: 内板高
    :param calcThresBig:识别偏大阈值
    :param calcThresSmall: 识别偏小阈值
    :param boardColor: 物料区域的彩色图像
    :param boardPos: 板的位置
    :return: 返回res,包含集中情况,需要分别去考虑.
    """
    global minLineLength, maxLineGap, lineLengthMin
    useImage = boardColor.copy()
    boardArea = width * height
    totalHeightPix, totalWidthPix = board.shape[:2]
    totalWidthMm, totalHeightMm = round(totalWidthPix / cp.mm2pix, 2), round(totalHeightPix / cp.mm2pix, 2)
    moveWidth13 = int(totalWidthPix * 0.21)
    moveWidthMid = int(totalWidthPix * 0.3)
    moveHeight = int(totalHeightPix * 0.25)
    res = {
        "result": "error",
        "box": None,
        "info": "",
        "calcSize": (totalWidthMm, totalHeightMm),
        "calcError": (0, 0)
    }

    widthMax = width / cp.mm2pix + calcThresBig
    widthMin = width / cp.mm2pix - calcThresSmall
    heightMax = height / cp.mm2pix + calcThresBig
    heightMin = height / cp.mm2pix - calcThresSmall
    moveAngleUsed = board.copy()
    try:
        if boardPos == "up":
            cv.rectangle(moveAngleUsed, (0, 0), (moveWidth13, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1], 0), (moveAngleUsed.shape[1] - moveWidth13, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (0, moveAngleUsed.shape[0] - moveHeight), (moveWidthMid, moveAngleUsed.shape[0]), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1] - moveWidthMid, moveAngleUsed.shape[0] - moveHeight),
                         (moveAngleUsed.shape[1], moveAngleUsed.shape[0]), 0, -1)
        else:
            cv.rectangle(moveAngleUsed, (0, 0), (moveWidthMid, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1], 0), (moveAngleUsed.shape[1] - moveWidthMid, moveHeight), 0, -1)
            cv.rectangle(moveAngleUsed, (0, moveAngleUsed.shape[0] - moveHeight), (moveWidth13, moveAngleUsed.shape[0]), 0, -1)
            cv.rectangle(moveAngleUsed, (moveAngleUsed.shape[1] - moveWidth13, moveAngleUsed.shape[0] - moveHeight),
                         (moveAngleUsed.shape[1], moveAngleUsed.shape[0]), 0, -1)

        image_show("MoveAngle", moveAngleUsed)

        cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
        if len(cnts) == 0:
            res["result"] = "error"
            res["info"] = "{} 框 找内板失败,没有找到任何的轮廓".format(boardPos)
            res["calcSize"] = (totalWidthMm, totalHeightMm)
            res["calcError"] = (round(totalWidthMm - width / cp.mm2pix, 2), round(totalHeightMm - height / cp.mm2pix))
            return res

        cntFindAgain = False  # 是否需要再找一遍轮廓
        _, (w, h), _ = cv.minAreaRect(cntsSorted[0])
        rectBox = cv.minAreaRect(cntsSorted[0])
        rectBoxPoints = np.int0(cv.boxPoints(rectBox))
        leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
        cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
        image_show("InnerBoardFinded", useImage)
        res["box"] = [leftTop, rightTop, rightBottom, leftBottom]
        widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
        heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)
        res["calcSize"] = (widthFinded, heightFinded)
        res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
        areaFinded = w * h
        if areaFinded < 0.7 * boardArea:
            res["result"] = "error"
            res["info"] = "{} 框 找内板失败,找到的内板面积过小".format(boardPos)
            return res
        elif boardArea > 1.4 * boardArea:
            res["result"] = "error"
            res["info"] = "{} 框 找内板失败,找到的内板的面积过大".format(boardPos)
        else:
            # 获取到物料边缘的距离
            line1 = [leftTop, rightTop]
            line2 = [rightTop, rightBottom]
            line3 = [rightBottom, leftBottom]
            line4 = [leftBottom, leftTop]

            line5 = [(0, 0), (totalWidthPix, 0)]
            line6 = [(totalWidthPix, 0), (totalWidthPix, totalHeightPix)]
            line7 = [(totalWidthPix, totalHeightPix), (0, totalHeightPix)]
            line8 = [(0, totalHeightPix), (0, 0)]

            offset1 = get_two_line_distance(line1, line5) / cp.mm2pix
            offset2 = get_two_line_distance(line2, line6) / cp.mm2pix
            offset3 = get_two_line_distance(line3, line7) / cp.mm2pix
            offset4 = get_two_line_distance(line4, line8) / cp.mm2pix

            print("offsetMm: {:.2f}, {:.2f}, {:.2f}, {:.2f}, offsetPix: {},{},{},{}".format(
                offset1, offset2, offset3, offset4, int(offset1 * cp.mm2pix), int(offset2 * cp.mm2pix),
                int(offset3 * cp.mm2pix), int(offset4 * cp.mm2pix)))
            if boardPos == "up":
                offset1Limit = 10
                offset3Limit = upDownSlice / cp.mm2pix - 15
            else:
                offset1Limit = upDownSlice / cp.mm2pix - 15
                offset3Limit = 10

            # 推测第一边
            if offset1 < offset1Limit and offset3 > offset3Limit:
                findLineBoard = board.copy()[:int(board.shape[0] * 0.4), :]
                image_show("boardUsedForLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.2, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeTop", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        lineLength = distance((x1, y1,), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle > 45):
                            continue
                        if boardPos == "up":
                            yMin = 10 * cp.mm2pix
                            yMax = board.shape[0] - height - 10 * cp.mm2pix
                        else:
                            yMin = 10 * cp.mm2pix
                            yMax = upDownSlice + 25 * cp.mm2pix
                        if abs(y2 - y1) < 10 * cp.mm2pix and abs(x2 - x1) > 5 * cp.mm2pix and yMin < y1 < yMax and \
                                yMin < y2 < yMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)

                if len(linesList) >= 2:
                    image_show("EdgeFindedTop", board1)
                    cntFindAgain = True
                    if boardPos == "up":
                        linesListFinal = sorted(linesList, key=lambda x: x[1])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[1], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    y1 = targetLine[0][1]
                    y2 = targetLine[1][1]
                    slicePos = int(min(y1, y2))  # 按照最小的那个去截取
                    moveAngleUsed[:slicePos, :] = 0
                    image_show("moveAngleAfterSliceTop", moveAngleUsed)

            # 如果第一边位置是对的,推测第三边
            if offset1 > offset1Limit and offset3 < offset3Limit:
                yOffset = int(board.shape[0] * 0.6)
                findLineBoard = board.copy()[yOffset:, :]
                image_show("boardUsedForLine", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.2, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeBottom", findLineBoard)

                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        y1 += yOffset
                        y2 += yOffset
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) > 45:
                            continue
                        if boardPos == "up":
                            yMin = board1.shape[0] - upDownSlice - 30 * cp.mm2pix
                            yMax = board1.shape[0] - upDownSlice + 10 * cp.mm2pix
                        else:
                            yMin = board1.shape[0] - 200 * cp.mm2pix
                            yMax = board1.shape[0] - 10 * cp.mm2pix

                        if abs(y2 - y1) < 10 * cp.mm2pix and abs(x2 - x1) > 5 * cp.mm2pix and yMin < y1 < yMax and \
                                yMin < y2 < yMax and lineLength > lineLengthMin:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)

                if len(linesList) >= 2:
                    image_show("EdgeFindedBottom", board1)
                    cntFindAgain = True
                    if boardPos == "up":
                        linesListFinal = sorted(linesList, key=lambda x: x[1])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[1], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    y1 = targetLine[0][1]
                    y2 = targetLine[1][1]
                    slicePos = int(max(y1, y2))  # 按最大的那个去截取
                    moveAngleUsed[slicePos:, :] = 0
                    image_show("moveAngleAfterSliceBottom", moveAngleUsed)

            offset24Limit = 12
            # 如果第二边是对的,第四边是错误的,就证明第四边需要重新加载.
            if offset2 > 10 and offset4 < offset24Limit or innerLine and (widthFinded < widthMin or widthFinded > widthMax):
                findLineBoard = board.copy()[:, :int(board.shape[1] * 0.25)]
                image_show("boardUsed", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeLeft", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) < 45:
                            continue

                        xMin = 15 * cp.mm2pix
                        xMax = board1.shape[1] * 0.3
                        if boardPos == "up":
                            yMin = 10 * cp.mm2pix
                            yMax = board1.shape[0] - upDownSlice
                        else:
                            yMin = upDownSlice
                            yMax = board1.shape[0] - 10 * cp.mm2pix
                        if abs(x2 - x1) < 10 * cp.mm2pix and abs(y2 - y1) > 5 * cp.mm2pix and xMin < x1 < xMax and \
                                xMin < x2 < xMax and lineLength > lineLengthMin and yMin < y1 < yMax and yMin < y2 < yMax:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)
                if len(linesList) >= 2:
                    image_show("EdgeFindedLeft", board1)
                    cntFindAgain = True
                    if innerLine:
                        linesListFinal = sorted(linesList, key=lambda x: x[0], reverse=True)
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[0])
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    x1 = targetLine[0][0]
                    x2 = targetLine[1][0]
                    slicePos = int(min(x1, x2))
                    moveAngleUsed[:, :slicePos] = 0
                    image_show("moveAngleAfterSliceLeft", moveAngleUsed)

            if offset2 < offset24Limit and offset4 > 10 and (widthFinded < widthMin or widthFinded > widthMax):
                xOffset = int(board.shape[1] * 0.75)
                findLineBoard = board.copy()[:, xOffset:]
                image_show("boardUsed", findLineBoard)
                scharrX = cv.Scharr(findLineBoard, cv.CV_64F, 1, 0)
                scharrY = cv.Scharr(findLineBoard, cv.CV_64F, 0, 1)
                scharrX = cv.convertScaleAbs(scharrX)
                scharrY = cv.convertScaleAbs(scharrY)
                scharrXY = cv.addWeighted(scharrX, 0.1, scharrY, 0.1, 0)
                findLineBoard = scharrXY.copy()
                image_show("ScharrXYEdgeLeft", findLineBoard)
                lines = cv.HoughLinesP(findLineBoard, 1, np.pi / 180, 100, minLineLength, maxLineGap)
                board1 = boardColor.copy()
                linesList = []
                for line in lines:
                    for x1, y1, x2, y2 in line:
                        x1 += xOffset
                        x2 += xOffset
                        lineLength = distance((x1, y1), (x2, y2))
                        lineK, lineB = get_line_k_and_b((x1, y1), (x2, y2))
                        lineAngle = get_angle_by_k(lineK)
                        if abs(lineAngle) < 45:
                            continue

                        xMin = board1.shape[1] * 0.7
                        xMax = board1.shape[1] - 15 * cp.mm2pix
                        if boardPos == "up":
                            yMin = 10 * cp.mm2pix
                            yMax = board1.shape[0] - upDownSlice
                        else:
                            yMin = upDownSlice
                            yMax = board1.shape[0] - 10 * cp.mm2pix
                        if abs(x2 - x1) < 10 * cp.mm2pix and abs(y2 - y1) > 5 * cp.mm2pix and xMin < x1 < xMax and \
                                xMin < x2 < xMax and lineLength > lineLengthMin and yMin < y1 < yMax and yMin < y2 < yMax:
                            linesList.append([x1, y1])
                            linesList.append([x2, y2])
                            cv.line(board1, (x1, y1), (x2, y2), (0, 255, 0), 3)
                if len(linesList) >= 2:
                    image_show("EdgeFindedRight", board1)
                    cntFindAgain = True
                    if innerLine:
                        linesListFinal = sorted(linesList, key=lambda x: x[0])
                    else:
                        linesListFinal = sorted(linesList, key=lambda x: x[0], reverse=True)
                    targetLine = [linesListFinal[0], linesListFinal[1]]
                    x1 = targetLine[0][0]
                    x2 = targetLine[1][0]
                    slicePos = int(max(x1, x2))
                    moveAngleUsed[:, slicePos:] = 0
                    image_show("moveAngleAfterSliceRight", moveAngleUsed)

            if cntFindAgain:
                cnts = cv.findContours(moveAngleUsed.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
                cnts = imutils.grab_contours(cnts)
                cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
                rectBox = cv.minAreaRect(cntsSorted[0])
                rectBoxPoints = np.int0(cv.boxPoints(rectBox))
                useImage = boardColor.copy()
                cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
                image_show("InnerBoardFindedByFillEdgeZero", useImage)
                leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
                res["box"] = leftTop, rightTop, rightBottom, leftBottom
                widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
                heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)

            topLineAngle = get_angle_by_k(get_line_k(leftTop, rightTop))
            if abs(topLineAngle) > 18:
                res["result"] = "error"
                res["info"] = "识别的内框的第一边的角度太大,角度为: {:.2f}".format(topLineAngle)
                res["calcSize"] = (widthFinded, heightFinded)
                res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                return res

            resByExtendFlag = False
            # 再计算一次是否有错误的信息
            line1 = [leftTop, rightTop]
            line2 = [rightTop, rightBottom]
            line3 = [rightBottom, leftBottom]
            line4 = [leftTop, leftBottom]

            offset1 = get_two_line_distance(line1, line5) / cp.mm2pix
            offset2 = get_two_line_distance(line2, line6) / cp.mm2pix
            offset3 = get_two_line_distance(line3, line7) / cp.mm2pix
            offset4 = get_two_line_distance(line4, line8) / cp.mm2pix
            if min(offset1, offset3) < 8 or max(offset2,offset4) < 5:
                # 这里再看看是不是中缝的问题,如果中缝有问题,就推测中缝
                if boardPos == "up" and extendMiddle and offset1 > 10 and offset3 < 10:
                    # 推测上框的中缝
                    newBox = get_new_box_by_edge_and_width([leftTop, rightTop, rightBottom, leftBottom], height, boardPos, boardColor)
                    if newBox is not None:
                        resByExtendFlag = True
                        res["box"] = newBox
                        leftTop, rightTop, rightBottom, leftBottom = newBox
                        widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
                        heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)
                        res["calcSize"] = (widthFinded, heightFinded)
                        res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                        res["info"] = "识别成功,通过宽和第一边推测中缝"
                        useImg = boardColor.copy()
                        cv.drawContours(useImg, [np.array(newBox)], -1, (0, 255, 0), 3)
                        image_show("InnerBoardFindedByExtendForMiddle", useImg, 0, True)
                elif boardPos == "down" and extendMiddle and offset1 < 10 and offset3 > 10:
                    newBox = get_new_box_by_edge_and_width([leftTop, rightTop, rightBottom, leftBottom], height, boardPos,
                                                           boardColor)
                    if newBox is not None:
                        resByExtendFlag = True
                        res["box"] = newBox
                        leftTop, rightTop, rightBottom, leftBottom = newBox
                        widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
                        heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)
                        res["calcSize"] = (widthFinded, heightFinded)
                        res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                        res["info"] = "识别成功,通过宽和第三边推测中缝"
                        useImg = boardColor.copy()
                        cv.drawContours(useImg, [np.array(newBox)], -1, (0, 255, 0), 3)
                        image_show("InnerBoardFindedByExtendForMiddle", useImg, 0, True)
                else:
                    res["result"] = "big"
                    res["info"] = "识别的内框太靠近物料边缘: {:.2f},{:.2f},{:.2f},{:.2f}".format(offset1, offset2, offset3, offset4)
                    res["calcSize"] = (widthFinded, heightFinded)
                    res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                    return res

            res["calcSize"] = (widthFinded, heightFinded)
            res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))

            if widthFinded < widthMin or heightFinded < heightMin:
                if boardPos == "down" and heightFinded < heightMin and widthMin < widthFinded < widthMax:
                    middleLineY = get_two_points_middle(leftTop, rightTop)[1]
                    totalBoardY = upDownSlice
                    if (totalBoardY - middleLineY) > 7 * cp.mm2pix or (totalBoardY - middleLineY) < -20 * cp.mm2pix:
                        middleIsOk = False
                    else:
                        middleIsOk = True
                    if middleIsOk:
                        newBox = get_new_box_by_middle_and_width([leftTop, rightTop, rightBottom, leftBottom], height, boardPos,
                                                                 boardColor)
                        if newBox is not None:
                            res["box"] = newBox
                            resByExtendFlag = True
                            leftTop, rightTop, rightBottom, leftBottom = newBox
                            widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)
                            heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)
                            res["calcSize"] = (widthFinded, heightFinded)
                            res["calcError"] = (round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2))
                            res["info"] = "识别成功,通过宽和中缝推测另外一边"
                            useImg = boardColor.copy()
                            cv.drawContours(useImg, [np.array(newBox)], -1, (0, 255, 0), 3)
                            image_show("InnerBoardFindedByExtend", useImg)
                        else:
                            res["result"] = "small"
                            res["info"] = "{} 框,识别的尺寸过小,识别尺寸:{}".format(boardPos, res["calcSize"])
                            return res
                    else:
                        res["result"] = "small"
                        res["info"] = "{} 框,识别的尺寸过小,识别尺寸:{}".format(boardPos, res["calcSize"])
                        return res
                else:

                    res["result"] = "small"
                    res["info"] = "{} 框,识别的尺寸过小,识别尺寸:{}".format(boardPos, res["calcSize"])
                    return res
            if widthFinded > widthMax or heightFinded > heightMax:
                res["result"] = "big"
                res["info"] = "{} 框,识别的尺寸过大,识别尺寸:{}".format(boardPos, res["calcSize"])
                return res

            boxFinded = res["box"]
            if boardPos == "down":
                downBoxPoints = [(p[0], p[1] + heightHalf - upDownSlice) for p in boxFinded]
                isOverlap = check_two_box_is_overlap(upBox, downBoxPoints)
                if isOverlap:
                    res["result"] = "error"
                    res["info"] = "上下框出现叠板,识别失败~"
                    return res
            # 检测一下左边和右边距离物料区域边缘的距离,如果误差在20个mm以上,就认为是错误的.
            leftCutLine = (leftTop, leftBottom)
            rightCutLine = (rightTop, rightBottom)
            leftBoardLine = ((0, 0), (0, board.shape[0]))
            rightBoardLine = ((board.shape[1], 0), (board.shape[1], board.shape[0]))
            leftOffset = get_two_line_distance(leftCutLine, leftBoardLine)
            rightOffset = get_two_line_distance(rightCutLine, rightBoardLine)
            leftRightLineOffsetMm = (leftOffset - rightOffset) / cp.mm2pix
            print("左右到物料边缘的误差: {:.1f}".format(leftRightLineOffsetMm))
            if abs(leftRightLineOffsetMm) > leftRightLineOffsetThres:
                res["result"] = "error"
                res["info"] = "识别的左右边框到物料边缘的距离差异太大,相差值: {:.1f},阈值:{}".format(leftRightLineOffsetMm,
                                                                             leftRightLineOffsetThres)
                widthFinded = distance(leftTop, rightTop)
                heightFinded = distance(leftTop, leftBottom)
                res["calcSize"] = (round(widthFinded / cp.mm2pix, 2), round(heightFinded / cp.mm2pix, 2))
                res["calcError"] = (
                    abs(round((widthFinded - width) / cp.mm2pix, 2)), abs(round((heightFinded - height) / cp.mm2pix)))
                return res

            if resByExtendFlag:
                res["result"] = "okByExtend"
            else:
                res["result"] = "ok"
                res["info"] = "识别成功!"
            return res

    except Exception as e:
        errorInfo = "in  check_inner_board() error: {}".format(str(e))
        print(errorInfo)
        res["result"] = "error"
        res["info"] = errorInfo
        res["calcSize"] = (totalWidthMm, totalHeightMm)
        res["calcError"] = (round(totalWidthMm - width / cp.mm2pix, 2), round(totalHeightMm - height / cp.mm2pix, 2))
        return res


def get_new_box_by_middle_and_width(box, height, boardPos, boardColor):
    """
    根据原来的框以及宽高和中缝推测新的框
    :param box:
    :param width:
    :param height:内框的高度
    :return:
    """
    leftTop, rightTop, rightBottom, leftBottom = box
    leftK, leftB = get_line_k_and_b(leftTop, leftBottom)
    rightK, rightB = get_line_k_and_b(rightTop, rightBottom)
    heightOffset = height - distance(leftTop, leftBottom)
    h, w = boardColor.shape[:2]

    if boardPos == "down":
        if leftK is None or rightK is None:
            newLeftBottom = [int(leftBottom[0]), int(leftBottom[1] + heightOffset)]
            newRightBottom = [int(rightBottom[0]), int(rightBottom[1] + heightOffset)]
        else:
            yOffset = abs(heightOffset * np.sin(trans_k_to_rad(leftK)))
            xOffset = abs(heightOffset * np.cos(trans_k_to_rad(leftK)))
            xOffset = xOffset if leftBottom[0] - leftTop[0] > 0 else -xOffset
            newLeftBottom = [int(leftBottom[0] + xOffset), int(leftBottom[1] + yOffset)]
            newRightBottom = [int(rightBottom[0] + xOffset), int(rightBottom[1] + yOffset)]
        newLeftTop = leftTop
        newRightTop = rightTop
        thirdLineToBoardEdge = distance(get_two_points_middle(newLeftBottom, newRightBottom),
                                        get_two_points_middle((0, w), (w, h))) / cp.mm2pix

    else:
        if leftK is None or rightK is None:
            newLeftTop = [int(leftTop[0]), int(leftTop[1] - heightOffset)]
            newRightTop = [int(rightTop[0]), int(rightTop[1] - heightOffset)]
        else:
            yOffset = abs(heightOffset * np.sin(trans_k_to_rad(leftK)))
            xOffset = abs(heightOffset * np.cos(trans_k_to_rad(leftK)))
            xOffset = xOffset if leftTop[0] - leftBottom[0] > 0 else -xOffset
            newLeftTop = [int(leftBottom[0] + xOffset), int(leftBottom[1] - yOffset)]
            newRightTop = [int(rightBottom[0] + xOffset), int(rightBottom[1] - yOffset)]
        newLeftBottom = leftBottom
        newRightBottom = rightBottom
        thirdLineToBoardEdge = distance(get_two_points_middle(newLeftTop, newRightTop),
                                        get_two_points_middle((0, 0), (w, 0))) / cp.mm2pix
    isLongCropper = True if thirdLineToBoardEdge >= 70 else False
    print("推测的胶边和铜箔的长度 = {},是否是长铜箔 = {}".format(thirdLineToBoardEdge, isLongCropper))
    newBox = [newLeftTop, newRightTop, newRightBottom, newLeftBottom] if not isLongCropper else None
    return newBox


def get_new_box_by_edge_and_width(box, height, boardPos, boardColor):
    """
    根据原来的框以及宽高和中缝推测新的框
    :param box:
    :param width:
    :param height:内框的高度
    :return:
    """
    leftTop, rightTop, rightBottom, leftBottom = box
    leftK, leftB = get_line_k_and_b(leftTop, leftBottom)
    rightK, rightB = get_line_k_and_b(rightTop, rightBottom)
    heightOffset = height
    h, w = boardColor.shape[:2]

    if boardPos == "down":
        if leftK is None or rightK is None:
            newLeftTop = [int(leftTop[0]), int(leftBottom[1] - heightOffset)]
            newRightTop = [int(rightTop[0]), int(rightBottom[1] - heightOffset)]
        else:
            yOffset = abs(heightOffset * np.sin(trans_k_to_rad(leftK)))
            xOffset = abs(heightOffset * np.cos(trans_k_to_rad(leftK)))
            xOffset = xOffset if leftTop[0] - leftBottom[0] > 0 else -xOffset
            newLeftTop = [int(leftBottom[0] + xOffset), int(leftBottom[1] - yOffset)]
            newRightTop = [int(rightBottom[0] + xOffset), int(rightBottom[1] - yOffset)]
        newLeftBottom = leftBottom
        newRightBottom = rightBottom
        thirdLineToBoardEdge = distance(get_two_points_middle(newLeftTop, newRightTop),
                                        get_two_points_middle((0, w), (w, h))) / cp.mm2pix

    else:
        if leftK is None or rightK is None:
            newLeftBottom = [int(leftBottom[0]), int(leftTop[1] + heightOffset)]
            newRightBottom = [int(rightBottom[0]), int(rightTop[1] + heightOffset)]
        else:
            yOffset = abs(heightOffset * np.sin(trans_k_to_rad(leftK)))
            xOffset = abs(heightOffset * np.cos(trans_k_to_rad(leftK)))
            xOffset = xOffset if leftBottom[0] - leftTop[0] > 0 else -xOffset
            newLeftBottom = [int(leftTop[0] + xOffset), int(leftTop[1] + yOffset)]
            newRightBottom = [int(rightTop[0] + xOffset), int(rightTop[1] + yOffset)]
        newLeftTop = leftTop
        newRightTop = rightTop
        thirdLineToBoardEdge = distance(get_two_points_middle(newLeftBottom, newRightBottom),
                                        get_two_points_middle((0, 0), (w, 0))) / cp.mm2pix

    newBox = [newLeftTop, newRightTop, newRightBottom, newLeftBottom]
    return newBox


def check_inner_board_for_size_check(boardMoveAngle, width, height, calcThresBig, boardColor):
    """
    尺寸确认那里的识别检测,这里会把识别的尺寸无论是偏大还是偏小,只要找到的是对的就返回给.
    :param boardMoveAngle:最后处理掉的包含内板的二值图像
    :param width:内板的宽
    :param height:内板的高
    :param calcThresBig:偏大阈值,首次尺寸确认的时候只使用偏大阈值
    :param boardColor:
    :return:
    """
    # 尺寸确认的时候,只使用偏大阈值
    useImage = boardColor.copy()
    totalHeight, totalWidth = boardMoveAngle.shape[:2]
    boardArea = width * height
    totalWidth = round(totalWidth / cp.mm2pix, 2)
    totalHeight = round(totalHeight / cp.mm2pix, 2)
    res = {
        "result": "error",
        "box": None,
        "info": "",
        "calcSize": (totalWidth, totalHeight),
        "calcError": (0, 0),
    }
    cnts = cv.findContours(boardMoveAngle.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    cntsSorted = sorted(cnts, key=cv.contourArea, reverse=True)
    try:
        _, (w, h), _ = cv.minAreaRect(cntsSorted[0])
        areaFinded = w * h
        if len(cnts) == 0:
            res["result"] = "error"
            res["info"] = "找内板失败,没有找到任何轮廓"
            res["calcSize"] = (totalWidth, totalHeight)
            res["calcError"] = (round(totalWidth - width / cp.mm2pix, 2), round(totalHeight - height / cp.mm2pix, 2))
            return res
        elif 1.3 * boardArea > areaFinded > 0.8 * boardArea:
            rectBox = cv.minAreaRect(cntsSorted[0])
            rectBoxPoints = np.int0(cv.boxPoints(rectBox))
            cv.drawContours(useImage, [rectBoxPoints], -1, (0, 255, 0), 3)
            image_show("InnerBoardFinded", useImage)
            leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectBoxPoints)
            widthFinded = round(distance(leftTop, rightTop) / cp.mm2pix, 2)  # 找到的宽,单位mm
            heightFinded = round(distance(leftTop, leftBottom) / cp.mm2pix, 2)  # 找到的高,单位mm
            widthError, heightError = round(widthFinded - width / cp.mm2pix, 2), round(heightFinded - height / cp.mm2pix, 2)
            res["calcSize"] = (widthFinded, heightFinded)
            res["calcError"] = (widthError, heightError)
            # 过滤掉一定是错误的线.第一,如果找到的两个顶点
            # 如果找到的第一边的一个顶点,太接近物料的顶点,就认为这条线肯定是找错了.

            widthMax = width / cp.mm2pix + calcThresBig
            widthMin = width / cp.mm2pix - calcThresBig
            heightMax = height / cp.mm2pix + calcThresBig
            heightMin = height / cp.mm2pix - calcThresBig
            res["box"] = [leftTop, rightTop, rightBottom, leftBottom]

            if widthFinded > widthMax or heightFinded > heightMax:
                if heightFinded > heightMax and max(leftBottom[1], rightBottom[1]) > (totalHeight - 10) * cp.mm2pix:
                    # 如果中缝没找到,并且第三边的位置在底部,就考虑是中缝位置不对,直接延长
                    newBox = get_new_box_for_no_middle(res["box"], height, "up")
                    leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(newBox)
                    res["box"] = newBox
                    if max(leftBottom[1], rightBottom[1]) > (totalHeight - 30) * cp.mm2pix:
                        res["result"] = "error"
                        res["info"] = "{}框 找到的内板中缝,太靠近下边缘,判定找板失败".format("up")
                        return res
                    widthFinded = distance(leftTop, rightTop)
                    heightFinded = distance(leftTop, leftBottom)
                    res["calcSize"] = (round(widthFinded / cp.mm2pix, 2), round(heightFinded / cp.mm2pix, 2))
                    res["calcError"] = (
                        abs(round((widthFinded - width) / cp.mm2pix, 2)), abs(round((heightFinded - height) / cp.mm2pix)))
                    res["info"] = "识别成功,根据尺寸和第一边推测中缝位置"
                    useImg = boardColor.copy()
                    cv.drawContours(useImg, [np.array(newBox)], -1, (0, 255, 0), 3)
                    image_show("InnerBoardFindedByExtendForNoMiddle", useImg)
                    res["result"] = "ok"
                    return res
                res["result"] = "big"
                res["info"] = "识别尺寸过大"
                return res

            if widthFinded < widthMin or heightFinded < heightMin:
                res["result"] = "small"
                res["info"] = "识别尺寸过小"
                return res

            if get_two_points_middle(leftTop, rightTop)[1] < 8 * cp.mm2pix:
                res["result"] = "error"
                res["info"] = "{}框 找到的内板第一边,太靠近上边缘,判定找板失败".format("up")
                return res

            if max(leftBottom[1], rightBottom[1]) > (totalHeight - 30) * cp.mm2pix:
                res["result"] = "error"
                res["info"] = "{}框 找到的内板中缝,太靠近下边缘,判定找板失败".format("up")
                return res
            res["result"] = "ok"
            res["info"] = "识别成功!"
            return res
        else:
            res["result"] = "error"
            res["info"] = "识别的面积过大"
            res["calcSize"] = (totalWidth, totalHeight)
            res["calcError"] = (round(totalWidth - width / cp.mm2pix, 2), round(totalHeight - height / cp.mm2pix))
            return res
    except Exception as e:
        errorInfo = "in check_inner_board_first_check() error:{}".format(str(e))
        res["result"] = "error"
        res["info"] = errorInfo
        res["calcSize"] = (totalWidth, totalHeight)
        res["calcError"] = (round(totalWidth - width / cp.mm2pix, 2), round(totalHeight - height / cp.mm2pix, 2))
        return res


def get_lines_with_boxes(image, totalBoardNoAnlge, totalBoardBox, totalBoardThresWithAngle, upBox, downBox, transMtx, topRemain,
                         leftRemain,bottomRemain, rightRemain,totalBoardOffset):
    """
    根据框的内容去获取切线
    :param image:
    :param totalBoard:
    :param totalBoardBox:
    :param totalBoardThres:
    :param upBox:
    :param downBox:
    :param transMtx:
    :param topRemain:
    :param leftRemain:
    :param bottomRemain:
    :param rightRemain:
    :return:
    """
    if len(image.shape) == 3:
        image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    imageColor = cv.cvtColor(image, cv.COLOR_GRAY2BGR)

    _, (w, h), totalBoardAngle = totalBoardBox
    # print ((cx, cy), (w, h), totalBoardAngle)
    upLeftTop, upRightTop, upRightBottom, upLeftBottom = upBox
    downLeftTop, downRightTop, downRightBottom, downLeftBottom = downBox

    middleOffsetPix = int(cp.mm2pix * cp.middleOffset)
    # 识别框补偿,上框上移1个mm,下框上移一个mm.
    upLeftTop = [upLeftTop[0],upLeftTop[1] - middleOffsetPix]
    upRightTop = [upRightTop[0],upRightTop[1] - middleOffsetPix]
    upRightBottom = [upRightBottom[0],upRightBottom[1] - middleOffsetPix]
    upLeftBottom = [upLeftBottom[0],upLeftBottom[1] - middleOffsetPix]

    downLeftTop = [downLeftTop[0],downLeftTop[1] - middleOffsetPix]
    downRightTop = [downRightTop[0] ,downRightTop[1] - middleOffsetPix]
    downRightBottom = [downRightBottom[0],downRightBottom[1] - middleOffsetPix]
    downLeftBottom = [downLeftBottom[0],downLeftBottom[1] - middleOffsetPix]

    # cut_remain_pix_acbd如果不等于-1，则证明需要切割ac，bd边，那就需要进行下面的计算

    leftCutLineK = get_linear_fit_k_vertical(np.array([upLeftTop, upLeftBottom, downLeftTop, downLeftBottom]))
    # 直接分别求过四个点的直线的b参数，找出最值
    if leftCutLineK is None:
        leftCutLineB = min(upLeftTop[0], upLeftBottom[0], downLeftTop[0], downLeftBottom[0]) - leftRemain
    else:
        upLeftTopX = upLeftTop[1] - (upLeftTop[0] - leftRemain) * leftCutLineK
        upLeftBottomX = upLeftBottom[1] - (upLeftBottom[0] - leftRemain) * leftCutLineK
        downLeftTopX = downLeftTop[1] - (downLeftTop[0] - leftRemain) * leftCutLineK
        downLeftBottomX = downLeftBottom[1] - (downLeftBottom[0] - leftRemain) * leftCutLineK

        if leftCutLineK > 0:  # 当k大于0时，b越大，越靠左
            leftCutLineB = max(upLeftTopX, upLeftBottomX, downLeftTopX, downLeftBottomX)
        else:  # 当k小于0时，b越小，越靠左
            leftCutLineB = min(upLeftTopX, upLeftBottomX, downLeftTopX, downLeftBottomX)

    rightCutLineK = get_linear_fit_k_vertical(np.array([upRightBottom, upRightTop, downRightTop, downRightBottom]))
    # 直接分别求过四个点的直线的b参数，找出最值
    if rightCutLineK is None:
        rightCutLineB = max(upRightTop[0], upRightBottom[0], downRightTop[0], downRightBottom[0]) + rightRemain
    else:
        upRightTopX = upRightTop[1] - (upRightTop[0] + rightRemain) * rightCutLineK
        upRightBottomX = upRightBottom[1] - (upRightBottom[0] + rightRemain) * rightCutLineK
        downRightTopX = downRightTop[1] - (downRightTop[0] + rightRemain) * rightCutLineK
        downRightBottomX = downRightBottom[1] - (downRightBottom[0] + rightRemain) * rightCutLineK

        if rightCutLineK > 0:  # 当k大于0时，b越大，越靠左
            rightCutLineB = min(upRightTopX, upRightBottomX, downRightTopX, downRightBottomX)
        else:  # 当k小于0时，b越小，越靠左
            rightCutLineB = max(upRightTopX, upRightBottomX, downRightTopX, downRightBottomX)

    topCutLineK = get_line_k(upLeftTop, upRightTop)
    if topCutLineK is None:
        cv.destroyAllWindows()
        return False, None, None
    else:
        topCutLineB = topCutLineK * -1 * (upLeftTop[0]) + (upLeftTop[1] - topRemain)

    bottomCutLineK = get_line_k(downLeftBottom, downRightBottom)
    if bottomCutLineK is None:
        # 垂直，一定是异常
        cv.destroyAllWindows()
        return False, None, None, None
    else:
        bottomCutLineB = bottomCutLineK * -1 * (downLeftBottom[0]) + downLeftBottom[1] + bottomRemain

    # 四边都不切的逻辑寻找边线的算法
    boardLeftTop = [0, 0]
    boardRightTop = [w, 0]
    boardLeftBottom = [0, h]
    boardRightBottom = [w, h]

    # # 先将切线超过1,3边范围的的留边宽度置为0，也就是如果边线算出去了,就沿着物料区域的最外侧1个mm去切
    # leftTopY = upLeftTop[1] - topRemain
    # rightTopY = upRightTop[1] - topRemain
    # if leftTopY < 0 or rightTopY < 0:
    #     topRemain = 0

    # leftBottomY = downLeftBottom[1] + bottomRemain
    # rightBottomY = downRightBottom[1] + bottomRemain
    # if leftBottomY > totalBoard.shape[0] or rightBottomY > totalBoard.shape[0]:
    #     bottomRemain = 0

    findEdgeExtend = int(7 * cp.mm2pix)  # 找边缘的时候延长10个mm
    totalBoardExtendForFindEdge, _ = get_board_without_angle_3(image, totalBoardBox, findEdgeExtend)
    totalBoardThresForFindEdge, _ = get_board_without_angle_3(totalBoardThresWithAngle, totalBoardBox, findEdgeExtend)

    if topRemain == 0:
        topLineK, topLineB = find_first_edge_line(totalBoardExtendForFindEdge, totalBoardThresForFindEdge, findEdgeExtend)
        if topLineK is not None:
            topCutLineK, topCutLineB = topLineK, topLineB
        else:
            topCutLineK, topCutLineB = get_line_k_and_b(boardLeftTop, boardRightTop)
    if bottomRemain == 0:
        bottomLineK, bottomLineB = find_third_edge_line(totalBoardExtendForFindEdge, totalBoardThresForFindEdge , findEdgeExtend)
        if bottomLineK is not None:
            bottomCutLineK, bottomCutLineB = bottomLineK, bottomLineB
        else:
            bottomCutLineK, bottomCutLineB = get_line_k_and_b(boardLeftBottom, boardRightBottom)
    if leftRemain == 0:
        leftCutLineK, leftCutLineB = get_line_k_and_b(boardLeftBottom, boardLeftTop)
    if rightRemain == 0:
        rightCutLineK, rightCutLineB = get_line_k_and_b(boardRightTop, boardRightBottom)

    # ①求所有的交点，当上下左右四条边都切时

    leftTopCross = get_two_lines_intersection(topCutLineK, topCutLineB, leftCutLineK, leftCutLineB)
    rightTopCross = get_two_lines_intersection(topCutLineK, topCutLineB, rightCutLineK, rightCutLineB)
    leftBottomCross = get_two_lines_intersection(bottomCutLineK, bottomCutLineB, leftCutLineK, leftCutLineB)
    rightBottomCross = get_two_lines_intersection(bottomCutLineK, bottomCutLineB, rightCutLineK, rightCutLineB)

    if leftTopCross[0] is None or rightTopCross[0] is None or leftBottomCross[0] is None or \
            rightBottomCross[0] is None:
        cv.destroyAllWindows()
        return False, None, None, None
    extend = int(8 * cp.mm2pix)
    extendLeftRight = int(23 * cp.mm2pix)

    topCutLeftPoint = [- extend, topCutLineK * (- extend) + topCutLineB]
    topCutRightPoint = [extend + w, topCutLineK * (extend + w) + topCutLineB]

    # bottomCutRightPoint = [w + 10,
    #                        bottomCutLineK * (w + 10) + bottomCutLineB]

    bottomCutRightPoint = [w + extend, bottomCutLineK * (w + extend) + bottomCutLineB]
    bottomCutLeftPoint = [- extend, bottomCutLineK * (- extend) + bottomCutLineB]

    if leftCutLineK is None:
        leftCutLineBottom = [leftCutLineB, leftBottomCross[1] + extendLeftRight]
        leftCutLineTop = [leftCutLineB, leftTopCross[1] - extendLeftRight]
    elif leftCutLineK != 0:
        leftCutLineBottom = [((leftBottomCross[1] + extendLeftRight) - leftCutLineB) / leftCutLineK,
                             leftBottomCross[1] + extendLeftRight]
        leftCutLineTop = [(leftTopCross[1] - extendLeftRight - leftCutLineB) / leftCutLineK,
                          leftTopCross[1] - extendLeftRight]
    else:
        cv.destroyAllWindows()
        return False, None, None, None

    if rightCutLineK is None:
        rightCutLineTop = [rightCutLineB, rightTopCross[1] - extendLeftRight]
        rightCutLineBottom = [rightCutLineB, rightBottomCross[1] + extendLeftRight]
    elif rightCutLineK != 0:
        rightCutLineTop = [((rightTopCross[1] - extendLeftRight) - rightCutLineB) / rightCutLineK,
                           rightTopCross[1] - extendLeftRight]
        rightCutLineBottom = [((rightBottomCross[1] + extendLeftRight) - rightCutLineB) / rightCutLineK,
                              rightBottomCross[1] + extendLeftRight]
    else:
        cv.destroyAllWindows()
        return False, None, None, None

    # 求中线，如果求出来k和top，bottom差太多就返回错误
    middleCutLine = get_middle_cut_line(upLeftBottom, upRightBottom, downLeftTop, downRightTop)

    if middleCutLine[0] is None:
        # 垂直，一定是异常
        cv.destroyAllWindows()
        return False, None, None, None
    leftMiddleCross = get_two_lines_intersection(middleCutLine[0], middleCutLine[1], leftCutLineK, leftCutLineB)
    rightMiddleCross = get_two_lines_intersection(middleCutLine[0], middleCutLine[1], rightCutLineK, rightCutLineB)

    middleCutLineLeft = [leftMiddleCross[0] - 10,
                         (leftMiddleCross[0] - 10) * middleCutLine[0] + middleCutLine[1]]
    middleCutLineRight = [rightMiddleCross[0] + 10,
                          (rightMiddleCross[0] + 10) * middleCutLine[0] + middleCutLine[1]]

    # 变成大图中的点
    # cx, cy表示板的中心点，w，h是板的宽高，rotateAngle表示要旋转的角度
    (centerX, centerY), (w, h), totalBoardAngle = totalBoardBox
    rotatedCenter = (centerX,centerY)

    wHalf, hHalf = w // 2 - 1, h // 2 - 1
    M = cv.getRotationMatrix2D(rotatedCenter,-totalBoardAngle,1)
    centerOffset = totalBoardOffset

    # 获取物料区域在大图上的四个点的坐标.
    boardLeftTopBig = np.dot(M, [boardLeftTop[0] + centerOffset[0], boardLeftTop[1] + centerOffset[1], 1])
    boardRightTopBig = np.dot(M, [boardRightTop[0] + centerOffset[0], boardRightTop[1] + centerOffset[1], 1])
    boardRightBottomBig = np.dot(M, [boardRightBottom[0] + centerOffset[0], boardRightBottom[1] + centerOffset[1], 1])
    boardLeftBottomBig = np.dot(M, [boardLeftBottom[0] + centerOffset[0], boardLeftBottom[1] + centerOffset[1], 1])

    topCutLeftPointBig =np.dot(M, [topCutLeftPoint[0] + centerOffset[0], topCutLeftPoint[1] + centerOffset[1], 1])
    topCutRightPointBig =np.dot(M, [topCutRightPoint[0] + centerOffset[0], topCutRightPoint[1] + centerOffset[1], 1])
    bottomCutRightPointBig = np.dot(M, [bottomCutRightPoint[0] + centerOffset[0], bottomCutRightPoint[1] + centerOffset[1], 1])
    bottomCutLeftPointBig =  np.dot(M, [bottomCutLeftPoint[0] + centerOffset[0], bottomCutLeftPoint[1] + centerOffset[1], 1])
    leftCutLineBottomBig = np.dot(M, [leftCutLineBottom[0] + centerOffset[0], leftCutLineBottom[1] + centerOffset[1], 1])
    leftCutLineTopBig =np.dot(M, [leftCutLineTop[0] + centerOffset[0], leftCutLineTop[1] + centerOffset[1], 1])
    rightCutLineTopBig = np.dot(M, [rightCutLineTop[0] + centerOffset[0], rightCutLineTop[1] + centerOffset[1], 1])
    rightCutLineBottomBig = np.dot(M, [rightCutLineBottom[0] + centerOffset[0], rightCutLineBottom[1] + centerOffset[1], 1])
    middleCutLineLeftBig = np.dot(M, [middleCutLineLeft[0] + centerOffset[0], middleCutLineLeft[1] + centerOffset[1], 1])
    middleCutLineRightBig = np.dot(M, [middleCutLineRight[0] + centerOffset[0], middleCutLineRight[1] + centerOffset[1], 1])

    # 重新将端点定位到大图上去
    upLeftBottom = np.dot(M, [upLeftBottom[0] + centerOffset[0], upLeftBottom[1] + centerOffset[1], 1])
    upRightBottom = np.dot(M, [upRightBottom[0] + centerOffset[0], upRightBottom[1] + centerOffset[1], 1])
    upLeftTop =  np.dot(M, [upLeftTop[0] + centerOffset[0], upLeftTop[1] + centerOffset[1], 1])
    upRightTop = np.dot(M, [upRightTop[0] + centerOffset[0], upRightTop[1] + centerOffset[1], 1])
    downLeftTop =np.dot(M, [downLeftTop[0] + centerOffset[0], downLeftTop[1] + centerOffset[1], 1])
    downLeftBottom =  np.dot(M, [downLeftBottom[0] + centerOffset[0], downLeftBottom[1] + centerOffset[1], 1])
    downRightTop = np.dot(M, [downRightTop[0] + centerOffset[0], downRightTop[1] + centerOffset[1], 1])
    downRightBottom = np.dot(M, [downRightBottom[0] + centerOffset[0], downRightBottom[1] + centerOffset[1], 1])

    # 画出内框
    cv.line(imageColor, (int(upLeftBottom[0]), int(upLeftBottom[1])), (int(upRightBottom[0]), int(upRightBottom[1])),
            (0, 0, 255), 3)
    cv.line(imageColor, (int(upLeftBottom[0]), int(upLeftBottom[1])), (int(upLeftTop[0]), int(upLeftTop[1])), (0, 0, 255),
            3)
    cv.line(imageColor, (int(upRightBottom[0]), int(upRightBottom[1])), (int(upRightTop[0]), int(upRightTop[1])),
            (0, 0, 255), 3)
    cv.line(imageColor, (int(upLeftTop[0]), int(upLeftTop[1])), (int(upRightTop[0]), int(upRightTop[1])), (0, 0, 255), 3)
    cv.line(imageColor, (int(downLeftBottom[0]), int(downLeftBottom[1])),
            (int(downRightBottom[0]), int(downRightBottom[1])), (0, 0, 255), 3)
    cv.line(imageColor, (int(downLeftBottom[0]), int(downLeftBottom[1])), (int(downLeftTop[0]), int(downLeftTop[1])),
            (0, 0, 255), 3)
    cv.line(imageColor, (int(downRightBottom[0]), int(downRightBottom[1])), (int(downRightTop[0]), int(downRightTop[1])),
            (0, 0, 255), 3)
    cv.line(imageColor, (int(downLeftTop[0]), int(downLeftTop[1])), (int(downRightTop[0]), int(downRightTop[1])),
            (0, 0, 255), 3)

    # 画出上，下，左，右，中五条切线

    cv.line(imageColor, (int(topCutLeftPointBig[0]), int(topCutLeftPointBig[1])),
            (int(topCutRightPointBig[0]), int(topCutRightPointBig[1])), (0, 255, 0), 3)
    cv.putText(imageColor, '1', (int((topCutLeftPointBig[0] + topCutRightPointBig[0]) / 2),
                                 int((topCutLeftPointBig[1] + topCutRightPointBig[1]) / 2) - 60), cv.FONT_HERSHEY_COMPLEX,
               4, (255, 0, 0),
               12)
    cv.line(imageColor, (int(bottomCutRightPointBig[0]), int(bottomCutRightPointBig[1])),
            (int(bottomCutLeftPointBig[0]), int(bottomCutLeftPointBig[1])), (0, 255, 0), 3)
    cv.putText(imageColor, '3', (int((bottomCutRightPointBig[0] + bottomCutLeftPointBig[0]) / 2),
                                 int((bottomCutRightPointBig[1] + bottomCutLeftPointBig[1]) / 2) + 140),
               cv.FONT_HERSHEY_COMPLEX,
               4, (255, 0, 0), 12)

    cv.line(imageColor, (int(leftCutLineBottomBig[0]), int(leftCutLineBottomBig[1])),
            (int(leftCutLineTopBig[0]), int(leftCutLineTopBig[1])), (255, 0, 0), 3)
    cv.putText(imageColor, '2', (int((leftCutLineBottomBig[0] + leftCutLineTopBig[0]) / 2) - 110,
                                 int((leftCutLineBottomBig[1] + leftCutLineTopBig[1]) / 2)), cv.FONT_HERSHEY_COMPLEX,
               4, (255, 0, 0), 12)
    cv.line(imageColor, (int(rightCutLineTopBig[0]), int(rightCutLineTopBig[1])),
            (int(rightCutLineBottomBig[0]), int(rightCutLineBottomBig[1])), (255, 0, 0), 3)
    cv.putText(imageColor, '4', (int((rightCutLineTopBig[0] + rightCutLineBottomBig[0]) / 2) + 30,
                                 int((rightCutLineTopBig[1] + rightCutLineBottomBig[1]) / 2)), cv.FONT_HERSHEY_COMPLEX,
               4, (255, 0, 0), 12)
    cv.line(imageColor, (int(middleCutLineLeftBig[0]), int(middleCutLineLeftBig[1])),
            (int(middleCutLineRightBig[0]), int(middleCutLineRightBig[1])), (0, 255, 0), 3)

    # 综合10个点的信息
    topCutLeftPointRobot = pix_pos_to_robot(topCutLeftPointBig, transMtx)
    topCutRightPointRobot = pix_pos_to_robot(topCutRightPointBig, transMtx)
    bottomCutLeftPointRobot = pix_pos_to_robot(bottomCutLeftPointBig, transMtx)
    bottomCutRightPointRobot = pix_pos_to_robot(bottomCutRightPointBig, transMtx)
    leftCutLineBottomRobot = pix_pos_to_robot(leftCutLineBottomBig, transMtx)
    leftCutLineTopRobot = pix_pos_to_robot(leftCutLineTopBig, transMtx)
    rightCutLineTopRobot = pix_pos_to_robot(rightCutLineTopBig, transMtx)
    rightCutLineBottomRobot = pix_pos_to_robot(rightCutLineBottomBig, transMtx)
    middleCutLineLeftRobot = pix_pos_to_robot(middleCutLineLeftBig, transMtx)
    middleCutLineRightRobot = pix_pos_to_robot(middleCutLineRightBig, transMtx)

    boardLeftTopRobot = pix_pos_to_robot(boardLeftTopBig, transMtx)
    boardRightTopRobot = pix_pos_to_robot(boardRightTopBig, transMtx)
    boardRightBottomRobot = pix_pos_to_robot(boardRightBottomBig, transMtx)
    boardLeftBottomRobot = pix_pos_to_robot(boardLeftBottomBig, transMtx)
    # 计算裁切面积和刀使用的长度
    cutDisTotal = 0
    cutAreaTotal = 0
    if topRemain != 0:
        cutDis = distance(topCutLeftPointRobot, topCutRightPointRobot)
        area = cutDis * (distance(get_two_points_middle(topCutLeftPointRobot, topCutRightPointRobot),
                                  get_two_points_middle(boardLeftTopRobot, boardRightTopRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis
    if leftRemain != 0:
        cutDis = distance(leftCutLineBottomRobot, leftCutLineTopRobot)
        area = cutDis * (distance(get_two_points_middle(leftCutLineBottomRobot, leftCutLineTopRobot),
                                  get_two_points_middle(boardLeftTopRobot, boardLeftBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    if bottomRemain != 0:
        cutDis = distance(bottomCutRightPointRobot, bottomCutLeftPointRobot)
        area = cutDis * (distance(get_two_points_middle(bottomCutRightPointRobot, bottomCutLeftPointRobot),
                                  get_two_points_middle(boardLeftBottomRobot, boardRightBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    if rightRemain != 0:
        cutDis = distance(rightCutLineTopRobot, rightCutLineBottomRobot)
        area = cutDis * (distance(get_two_points_middle(rightCutLineTopRobot, rightCutLineBottomRobot),
                                  get_two_points_middle(boardRightTopRobot, boardRightBottomRobot)))
        cutAreaTotal += area
        cutDisTotal += cutDis

    # cv.imwrite("d:/cutLineImage/%s.jpg" % (time.strftime('%Y-%m-%d_%H-%M-%S', time.localtime())), cutLineImage)
    imageResut = get_board_widthout_angle(imageColor, totalBoardBox, extend=True)
    # imageResut = cv.resize(imageResut, (imageResut.shape[1] // 2, imageResut.shape[0] // 2), cv.INTER_AREA)
    image_show("resultImage", imageResut)
    # 以裁切机的实际切线为标准，计算前板长，后板长，总长
    # 先算中线中点
    firstBoardLength, totalBoardLength = get_board_length([topCutLeftPointRobot, topCutRightPointRobot],
                                                          [middleCutLineLeftRobot, middleCutLineRightRobot],
                                                          [bottomCutLeftPointRobot, bottomCutRightPointRobot])
    # 计算top_middle 和bottom_middle的角度,全部调整成一个方向,需要逆时针调整的时候为负数.
    topMiddleAngle = get_two_line_angle(middleCutLineRightRobot, middleCutLineLeftRobot, topCutRightPointRobot,
                                        topCutLeftPointRobot)  # 获取第一个角度
    bottomMiddleAngle = get_two_line_angle(middleCutLineRightRobot, middleCutLineLeftRobot, bottomCutRightPointRobot,
                                           bottomCutLeftPointRobot)  # 获取第二个角度
    # 是否切第一刀:
    isFirstCut = True if topRemain != 0 else False
    isThirdCut = True if bottomRemain != 0 else False
    cutLength = [round(cutDisTotal, 5), round(cutAreaTotal, 5)]
    cutWidth = distance(topCutLeftPointRobot, topCutRightPointRobot)
    return [topCutLeftPointRobot, topCutRightPointRobot, bottomCutRightPointRobot, bottomCutLeftPointRobot,
            leftCutLineBottomRobot, leftCutLineTopRobot, rightCutLineTopRobot, rightCutLineBottomRobot,
            middleCutLineLeftRobot,
            middleCutLineRightRobot, firstBoardLength, totalBoardLength, topMiddleAngle,
            bottomMiddleAngle], imageResut, cutLength, isFirstCut, isThirdCut, cutWidth


# def check_total_board_is_ok(imageSrc, width, height, boardBreak, totalHeightMax, totalHeightMin,jointNumber):
#     """
#     :param imageSrc:
#     :param width:
#     :param height:
#     :param boardBreak:
#     :param totalHeightMax 物料检测的最大值
#     :param totalHeightMin 物料检测的最小值
#     :return:
#     """
#     tablePos = int(np.mean(imageSrc[cp.sensorPos - 100:cp.sensorPos, cp.tablePosStart:cp.tablePosEnd]))
#     sensorPos = int(np.mean(imageSrc[cp.sensorPos:cp.sensorPos + 100, cp.tablePosStart:cp.tablePosEnd]))
#     totalBoardBox, totalBoardThres, totalBoardRes = find_total_board(imageSrc, width, height)
#     rectPoints = np.int0(cv.boxPoints(totalBoardBox))
#     leftTop, rightTop, rightBottom, leftBottom = get_rect_points_clockwise(rectPoints)
#     distanceByLine = point_by_line_distance(leftTop, rightTop)
#     mm = float(distanceByLine) / cp.mm2pix
#     w, h = totalBoardBox[1]
#     widthChecked, heightChecked = w / cp.mm2pix, h / cp.mm2pix
#     if not boardBreak:
#         maxThres = totalHeightMax
#         minThres = totalHeightMin
#     else:
#         maxThres = totalHeightMax + 200
#         minThres = totalHeightMin
#     retInfo = "传感器Pix = {} 最小值 = {},台布Pix = {} 最大值 = {},高度 = {:.2f},阈值 = ({},{})".format(sensorPos, cp.sensorValUsed,
#                                                                                          tablePos,
#                                                                                          cp.tableValUsed, heightChecked,
#                                                                                          minThres, maxThres)
#     totalBoardRes = put_table_sensor_pos_to_image(totalBoardRes, tablePos, sensorPos)
#     if sensorPos < cp.sensorValUsed or tablePos > cp.tableValUsed or (heightChecked < minThres and jointNumber == "2") \
#             or (heightChecked > maxThres and jointNumber == "2"):
#         # 将检测的区域也画上去.
#         return False, retInfo, totalBoardBox, totalBoardThres, totalBoardRes, mm
#     else:
#         return True, retInfo, totalBoardBox, totalBoardThres, totalBoardRes, mm


def get_width_height_by_image_name_2p(imageName):
    """
    根据图像
    :param imageName: 要处理的图片文件名称,合格的名称包括w_和h_这样的字符串,例如:10--11111--04-12_16-01--w_1552--h_1386--u_1_2_3_4--d_5_6_7_8.bmp
    :return:
    """
    if "w_" not in imageName or "h_" not in imageName:
        return None, None, None, None
    widthIndex = imageName.index("w_")
    heightIndex = imageName.index("h_")
    nameW = imageName[widthIndex + 2:widthIndex + 6]
    nameH = imageName[heightIndex + 2:heightIndex + 6]

    if "u_" not in imageName or "d_" not in imageName:
        upOffsetList = [0, 0, 0, 0]
        downOffsetList = [0, 0, 0, 0]
    else:
        uIndexStart = imageName.index("u_")
        dIndexStart = imageName.index("d_")
        uIndexEnd = imageName.index("--d")
        dIndexEnd = imageName.index(".bmp")

        upOffsetList = imageName[uIndexStart + 2:uIndexEnd].split("_")
        downOffsetList = imageName[dIndexStart + 2:dIndexEnd].split("_")
        upOffsetList = [int(offset) for offset in upOffsetList]
        downOffsetList = [int(offset) for offset in downOffsetList]
    return int(nameW), int(nameH), upOffsetList, downOffsetList


def point_by_line_distance(leftTop, rightTop, ):
    k = (leftTop[1] - rightTop[1]) / (leftTop[0] - rightTop[0])
    b = rightTop[1] - k * rightTop[0]
    y = (cp.tablePosStart + cp.tablePosEnd) / 2 * k + b
    # x = ((cp.tablePosStart+cp.tablePosEnd)/2 - b)/k
    # print("边到点的距离是：{}-{}={}".format(cp.sensorPos, "%.2f" % x,"%.2f" % (abs(cp.sensorPos-x))))
    return "%.2f" % (cp.sensorPos - y)


if __name__ == '__main__':
    # 先加载参数
    filePath = r"D:\2024\Yilianda"
    isFirstBoard = True  # 是否是首片,首片有首片的算法逻辑
    isFanzhuan = "否"
    res, data = db.get_line_cam_check_thres()
    totalHeightMax = data.get("totalHeightMax")
    totalHeightMin = data.get("totalHeightMin")
    boardBreak = False
    calcThresBig = 20
    calcThresSmall = 9
    innerToEdgeThres = 5
    jointNumber = "2"
    mtx = [
        [0, 1, 0],
        [1, 0, 0]
    ]
    remainEdge = [0, 15, 0, 15]
    topRemain, leftRemain, bottomRemain, rightRemain = [int(x * cp.mm2pix) for x in remainEdge]
    keepDir = filePath
    if not os.path.isdir(keepDir):
        keepDir, _ = os.path.split(filePath)

    keepOkPath = os.path.join(keepDir, "ok")
    keepOkResPath = os.path.join(keepDir, "cutlines")
    keepFailPath = os.path.join(keepDir, "fail")
    if not os.path.exists(keepOkPath):
        os.mkdir(keepOkPath)
    if not os.path.exists(keepOkResPath):
        os.mkdir(keepOkResPath)
    if not os.path.exists(keepFailPath):
        os.mkdir(keepFailPath)

    fileNames = []  # 保存要去识别的所有的图片
    if os.path.isfile(filePath):
        filePath, fileName = os.path.split(filePath)
        fileNames.append(fileName)
    else:
        for root, dirs, files in os.walk(filePath):
            if root != filePath:
                continue
            for file in files:
                if file[-4:] != ".bmp":
                    continue
                fileNames.append(file)

    for index, fileName in enumerate(fileNames):
        filePathReal = os.path.join(filePath, fileName)
        srcW, srcH, upLineOffset, downLineOffset = get_width_height_by_image_name_2p(fileName)
        if srcW is None or srcH is None:
            print("*" * 10 + "第 {} 张图 ({}),图像名称错误,已经跳过".format(index + 1, fileName) + "*" * 10)
            continue
        if 0 in upLineOffset or 0 in downLineOffset:
            isFirstBoard = True
        else:
            isFirstBoard = False
        print("*" * 10 + " 第 {} 张图 ({})".format(index + 1, fileName) + "*" * 10)
        imageTest = cv.imread(filePathReal, cv.IMREAD_GRAYSCALE)
        calcStart = time.time()
        totalBoardRes = check_total_board_is_ok(imageTest, totalHeightMax, totalHeightMin, boardBreak, jointNumber)
        res, hintInfo, totalBoardBox, totalBoardNoAngle, totalBoardOffset, totalBoardThresWithAngle, totalBoardResWithAngle = totalBoardRes
        print("物料检测结果: {}, {}".format(res, hintInfo))
        if isFirstBoard:
            #
            resFirst, boardSizeList, boardResList, upBoard = get_first_check_result(imageTest, srcW, srcH, calcThresBig, totalBoardBox, isFanzhuan)
            res, info, upBox, downBox, totalBoard, _ = get_boxes_first(imageTest, srcW, srcH, calcThresBig, calcThresSmall,
                                                                       totalBoardBox, totalBoardResWithAngle, isFanzhuan)
            upLineOffset, downLineOffset = get_line_offset(upBox, downBox, totalBoard, totalBoardBox)
            print("upLineOffset = {},downLineOffset = {}".format(upLineOffset, downLineOffset))
        else:
            res, info, upBox, downBox, totalBoard, _ = get_boxes(imageTest, srcW, srcH, calcThresBig,
                                                                 calcThresSmall, innerToEdgeThres,
                                                                 totalBoardBox, totalBoardThresWithAngle,
                                                                 upLineOffset, downLineOffset, isFanzhuan)

        if res:
            cutLines, imageRes, cutDis, isFirstCut, isThirdCut, cutWidth = get_lines_with_boxes(imageTest, totalBoard,
                                                                                                totalBoardBox,
                                                                                                totalBoardThresWithAngle,
                                                                                                upBox, downBox, mtx,
                                                                                                topRemain, leftRemain,
                                                                                                bottomRemain,
                                                                                                rightRemain,totalBoardOffset)
            print("算法耗时: {}".format(time.time() - calcStart))
            os.remove(filePathReal)
            imageRes = get_size_scale_image(imageRes, sizeScale=3)
            cv.imwrite(os.path.join(keepOkResPath, fileName), imageRes)
            cv.imwrite(os.path.join(keepOkPath, fileName), imageTest)
            print("识别成功")
            continue
        else:
            print("算法耗时: {}".format(time.time() - calcStart))
            cv.imwrite(os.path.join(keepFailPath, fileName), imageTest)
            os.remove(filePathReal)
            print("识别失败XXXXXXXXXXXXXXXXX")
            continue
